@@ -5,9 +5,11 @@ package echo
55
66import (
77 "bytes"
8+ stdContext "context"
89 "crypto/tls"
910 "encoding/json"
1011 "encoding/xml"
12+ "errors"
1113 "fmt"
1214 "io"
1315 "io/fs"
@@ -1119,10 +1121,137 @@ func TestContext_Validate(t *testing.T) {
11191121 e := New ()
11201122 c := e .NewContext (nil , nil )
11211123
1122- assert .Error (t , c .Validate (struct {}{}))
1124+ assert .ErrorIs (t , c .Validate (struct {}{}), ErrValidatorNotRegistered )
1125+ assert .ErrorIs (t , c .ValidateCtx (struct {}{}), ErrValidatorNotRegistered )
11231126
11241127 e .Validator = & validator {}
11251128 assert .NoError (t , c .Validate (struct {}{}))
1129+ assert .NoError (t , c .ValidateCtx (struct {}{}))
1130+ }
1131+
1132+ type validationFunc func (any ) error
1133+
1134+ func (v validationFunc ) Validate (i any ) error { return v (i ) }
1135+
1136+ type contextValidator struct {
1137+ validationFunc
1138+ validateCtx func (stdContext.Context , any ) error
1139+ }
1140+
1141+ func (v contextValidator ) ValidateCtx (ctx stdContext.Context , i any ) error {
1142+ return v .validateCtx (ctx , i )
1143+ }
1144+
1145+ func TestContext_Validate_legacyError (t * testing.T ) {
1146+ e := New ()
1147+ c := e .NewContext (nil , nil )
1148+ payload := & struct { Name string }{Name : "Jon Snow" }
1149+ wantErr := errors .New ("validation failed" )
1150+ e .Validator = validationFunc (func (i any ) error {
1151+ assert .Same (t , payload , i )
1152+ return wantErr
1153+ })
1154+ assert .Same (t , wantErr , c .Validate (payload ))
1155+ assert .Same (t , wantErr , c .ValidateCtx (payload ))
1156+ }
1157+
1158+ type validationWrapper struct {
1159+ contextValidator
1160+ err error
1161+ }
1162+
1163+ func (v validationWrapper ) Validate (any ) error { return v .err }
1164+
1165+ func TestContext_Validate_wrapper (t * testing.T ) {
1166+ e := New ()
1167+ c := e .NewContext (nil , nil )
1168+ wantErr := errors .New ("wrapper validation failed" )
1169+ e .Validator = validationWrapper {
1170+ contextValidator : contextValidator {
1171+ validateCtx : func (stdContext.Context , any ) error {
1172+ t .Fatal ("Validate must not call an embedded ValidateCtx method" )
1173+ return nil
1174+ },
1175+ },
1176+ err : wantErr ,
1177+ }
1178+ assert .Same (t , wantErr , c .Validate (struct {}{}))
1179+ }
1180+
1181+ func TestContext_ValidateCtx_withContext (t * testing.T ) {
1182+ ctx , cancel := stdContext .WithCancel (stdContext .Background ())
1183+ defer cancel ()
1184+ e := New ()
1185+ c := e .NewContext (nil , nil )
1186+ c .SetRequest (httptest .NewRequest (http .MethodGet , "/" , nil ).WithContext (ctx ))
1187+ payload := & struct { Name string }{Name : "Jon Snow" }
1188+ wantErr := errors .New ("validation failed" )
1189+ calls := 0
1190+ e .Validator = contextValidator {
1191+ validationFunc : func (any ) error {
1192+ t .Fatal ("Validate must not be called when ValidateCtx is implemented" )
1193+ return nil
1194+ },
1195+ validateCtx : func (got stdContext.Context , i any ) error {
1196+ calls ++
1197+ assert .Same (t , ctx , got )
1198+ assert .Same (t , payload , i )
1199+ return wantErr
1200+ },
1201+ }
1202+
1203+ assert .Same (t , wantErr , c .ValidateCtx (payload ))
1204+ assert .Equal (t , 1 , calls )
1205+
1206+ cancel ()
1207+ assert .Same (t , wantErr , c .ValidateCtx (payload ))
1208+ assert .Equal (t , 2 , calls )
1209+ }
1210+
1211+ func TestContext_ValidateCtx_requestReplacement (t * testing.T ) {
1212+ firstCtx , cancelFirst := stdContext .WithCancel (stdContext .Background ())
1213+ defer cancelFirst ()
1214+ secondCtx , cancelSecond := stdContext .WithCancel (stdContext .Background ())
1215+ defer cancelSecond ()
1216+
1217+ e := New ()
1218+ c := e .NewContext (httptest .NewRequest (http .MethodGet , "/" , nil ).WithContext (firstCtx ), nil )
1219+ var gotCtx stdContext.Context
1220+ e .Validator = contextValidator {
1221+ validationFunc : func (any ) error {
1222+ t .Fatal ("Validate must not be called when ValidateCtx is implemented" )
1223+ return nil
1224+ },
1225+ validateCtx : func (ctx stdContext.Context , _ any ) error {
1226+ gotCtx = ctx
1227+ return nil
1228+ },
1229+ }
1230+
1231+ assert .NoError (t , c .ValidateCtx (struct {}{}))
1232+ assert .Same (t , firstCtx , gotCtx )
1233+
1234+ c .SetRequest (c .Request ().WithContext (secondCtx ))
1235+ assert .NoError (t , c .ValidateCtx (struct {}{}))
1236+ assert .Same (t , secondCtx , gotCtx )
1237+ }
1238+
1239+ func TestContext_ValidateCtx_withoutRequest (t * testing.T ) {
1240+ e := New ()
1241+ c := e .NewContext (nil , nil )
1242+ var gotCtx stdContext.Context
1243+ e .Validator = contextValidator {
1244+ validateCtx : func (ctx stdContext.Context , i any ) error {
1245+ gotCtx = ctx
1246+ return nil
1247+ },
1248+ }
1249+
1250+ assert .NoError (t , c .ValidateCtx (struct {}{}))
1251+ if assert .NotNil (t , gotCtx ) {
1252+ assert .NoError (t , gotCtx .Err ())
1253+ assert .Nil (t , gotCtx .Done ())
1254+ }
11261255}
11271256
11281257func TestContext_QueryString (t * testing.T ) {
0 commit comments