package web import ( "errors" "testing" ) type StructWithInt struct { A int `binding:"Required"` } type StructWithPrimitives struct { A int `binding:"Required"` B string `binding:"Required"` C bool `binding:"Required"` D float64 `binding:"Required"` } type StructWithPrivateFields struct { A int `binding:"Required"` // must be validated b int `binding:"Required"` // will not be used } type StructWithInterface struct { A any `binding:"Required"` } type StructWithSliceInts struct { A []int `binding:"Required"` } type StructWithSliceStructs struct { A []StructWithInt `binding:"Required"` } type StructWithSliceInterfaces struct { A []any `binding:"Required"` } type StructWithStruct struct { A StructWithInt `binding:"Required"` } type StructWithStructPointer struct { A *StructWithInt `binding:"Required"` } type StructWithValidation struct { A int } func (sv StructWithValidation) Validate() error { if sv.A < 10 { return errors.New("too small") } return nil } type StructWithPointerValidation struct { A int } func (sv *StructWithPointerValidation) Validate() error { if sv.A < 10 { return errors.New("too small") } return nil } func TestValidationSuccess(t *testing.T) { var nilInterface *StructWithPointerValidation for _, x := range []any{ nil, 42, "foo", struct{ A int }{}, StructWithInt{42}, StructWithPrimitives{42, "foo", true, 12.34}, StructWithPrivateFields{12, 0}, StructWithInterface{"foo"}, StructWithSliceInts{[]int{1, 2, 3}}, StructWithSliceInterfaces{[]any{1, 2, 3}}, StructWithSliceStructs{[]StructWithInt{{1}, {2}}}, StructWithStruct{StructWithInt{3}}, StructWithStructPointer{&StructWithInt{3}}, StructWithValidation{42}, &StructWithPointerValidation{42}, nilInterface, } { if err := validate(x); err != nil { t.Error("Validation failed:", x, err) } } } func TestValidationFailure(t *testing.T) { for i, x := range []any{ StructWithInt{0}, StructWithPrimitives{0, "foo", true, 12.34}, StructWithPrimitives{42, "", true, 12.34}, StructWithPrimitives{42, "foo", false, 12.34}, StructWithPrimitives{42, "foo", true, 0}, StructWithPrivateFields{0, 1}, StructWithInterface{}, StructWithInterface{nil}, StructWithSliceInts{}, StructWithSliceInts{[]int{}}, StructWithSliceStructs{[]StructWithInt{}}, StructWithSliceStructs{[]StructWithInt{{0}, {2}}}, StructWithSliceStructs{[]StructWithInt{{2}, {0}}}, StructWithSliceInterfaces{[]any{}}, StructWithSliceInterfaces{nil}, StructWithStruct{StructWithInt{}}, StructWithStruct{StructWithInt{0}}, StructWithStructPointer{}, StructWithStructPointer{&StructWithInt{}}, StructWithValidation{2}, &StructWithPointerValidation{2}, } { if err := validate(x); err == nil { t.Error("Validation should fail:", i, x) } } }