@@ -192,3 +192,32 @@ func TestRouteDialTcpRetry_Dedup(t *testing.T) {
192192 t .Fatalf ("dedup should avoid retrying the same dialer, got call count=%d" , impl1 .CallCount ())
193193 }
194194}
195+
196+ func TestRouteDialTcpRetry_CanceledDoesNotPoisonDialer (t * testing.T ) {
197+ impl1 := & scriptedDialer {err : context .Canceled }
198+ impl2 := & scriptedDialer {conn : newMockConn (false , nil )}
199+ d1 := newTestRouteDialer (t , "d1" , impl1 )
200+ d2 := newTestRouteDialer (t , "d2" , impl2 )
201+
202+ cp := newTestControlPlaneWithGroup (consts .DialerSelectionPolicy_MinLastLatency , []* dialer.Dialer {d1 , d2 })
203+ networkType := & dialer.NetworkType {L4Proto : consts .L4ProtoStr_TCP , IpVersion : consts .IpVersionStr_4 , IsDns : false }
204+ d1 .MustGetLatencies10 (networkType ).AppendLatency (10 * time .Millisecond )
205+ d2 .MustGetLatencies10 (networkType ).AppendLatency (20 * time .Millisecond )
206+ group := cp .outbounds [consts .OutboundUserDefinedMin ]
207+ group .MustGetAliveDialerSet (networkType ).NotifyLatencyChange (d1 , true )
208+ group .MustGetAliveDialerSet (networkType ).NotifyLatencyChange (d2 , true )
209+
210+ _ , err := cp .RouteDialTcp (context .Background (), newTestRouteDialParam ())
211+ if ! errors .Is (err , context .Canceled ) {
212+ t .Fatalf ("expected context canceled, got: %v" , err )
213+ }
214+ if impl1 .CallCount () != 1 {
215+ t .Fatalf ("unexpected dialer-1 call count: got=%d want=1" , impl1 .CallCount ())
216+ }
217+ if impl2 .CallCount () != 0 {
218+ t .Fatalf ("unexpected dialer-2 call count: got=%d want=0" , impl2 .CallCount ())
219+ }
220+ if ! d1 .MustGetAlive (networkType ) {
221+ t .Fatal ("dialer should not be marked unavailable on context canceled" )
222+ }
223+ }
0 commit comments