@@ -177,6 +177,18 @@ func TestAddressResolver(t *testing.T) {
177177 wantPort : map [string ]string {"rewrite-me" : "9201" , "keep-me" : "9200" },
178178 metrics : wantMetrics {calls : 3 , rewrites : 1 , errors : 1 },
179179 },
180+ {
181+ name : "malformed URL keeps default and counts an error" ,
182+ inAddrs : map [string ]string {"alpha" : "10.0.0.1:9200" , "beta" : "10.0.0.2:9200" },
183+ resolver : func (_ context.Context , _ NodeInfo ) (* url.URL , error ) {
184+ // Empty Scheme/Host -- the kind of URL a resolver might
185+ // return from a buggy parse. The client must reject it
186+ // rather than enrolling a malformed connection.
187+ return & url.URL {}, nil
188+ },
189+ wantPort : map [string ]string {"alpha" : "9200" , "beta" : "9200" },
190+ metrics : wantMetrics {calls : 2 , rewrites : 0 , errors : 2 },
191+ },
180192 }
181193
182194 for _ , tt := range protocolTests {
@@ -389,7 +401,7 @@ func TestAddressResolver(t *testing.T) {
389401 ctx , cancel := context .WithCancel (t .Context ())
390402 cancel ()
391403 return ctx , func (_ context.Context , _ NodeInfo ) (* url.URL , error ) {
392- return nil , nil //nolint:nilnil // testing (nil, nil) protocol case
404+ return nil , nil
393405 }
394406 },
395407 wantErr : context .Canceled ,
@@ -399,12 +411,13 @@ func TestAddressResolver(t *testing.T) {
399411 setup : func (t * testing.T ) (context.Context , AddressResolverFunc ) {
400412 t .Helper ()
401413 ctx , cancel := context .WithCancel (t .Context ())
414+ t .Cleanup (cancel )
402415 var calls atomic.Int32
403416 return ctx , func (_ context.Context , _ NodeInfo ) (* url.URL , error ) {
404417 if calls .Add (1 ) == 1 {
405418 cancel ()
406419 }
407- return nil , nil //nolint:nilnil // testing (nil, nil) protocol case
420+ return nil , nil
408421 }
409422 },
410423 maxResolvers : 1 ,
@@ -433,7 +446,7 @@ func TestAddressResolver(t *testing.T) {
433446 return
434447 }
435448 require .NoError (t , err )
436- require .Equal (t , tt .wantNodes , len ( nodes ) )
449+ require .Len (t , nodes , tt .wantNodes )
437450 })
438451 }
439452
@@ -767,42 +780,83 @@ func TestAddressResolverRunner(t *testing.T) {
767780 "resolve param should be nil when AddressResolver is not set" )
768781 })
769782
770- t .Run ("runner context cancellation propagated" , func (t * testing.T ) {
771- t .Parallel ()
772-
773- ctx , cancel := context .WithCancel (t .Context ())
774- cancel ()
775-
776- tp , err := New (Config {
777- URLs : []* url.URL {testSeedURL (t )},
778- Transport : newResolverTestTransport (t , nodesJSON ),
779- HealthCheck : NoOpHealthCheck ,
780- AddressResolverRunner : func (ctx context.Context , _ []NodeInfo , _ AddressResolverFunc ) ([]ResolvedAddress , error ) {
783+ runnerEdgeCases := []struct {
784+ name string
785+ makeCtx func (t * testing.T ) context.Context
786+ runner AddressResolverRunnerFunc
787+ wantErr error
788+ wantNodes int
789+ }{
790+ {
791+ name : "context cancellation propagated" ,
792+ makeCtx : func (t * testing.T ) context.Context {
793+ t .Helper ()
794+ ctx , cancel := context .WithCancel (t .Context ())
795+ cancel ()
796+ return ctx
797+ },
798+ runner : func (ctx context.Context , _ []NodeInfo , _ AddressResolverFunc ) ([]ResolvedAddress , error ) {
781799 return nil , ctx .Err ()
782800 },
783- })
784- require .NoError (t , err )
801+ wantErr : context .Canceled ,
802+ },
803+ {
804+ name : "drops all returns ErrAllResolversFailed" ,
805+ runner : func (_ context.Context , _ []NodeInfo , _ AddressResolverFunc ) ([]ResolvedAddress , error ) {
806+ return nil , nil
807+ },
808+ wantErr : ErrAllResolversFailed ,
809+ },
810+ {
811+ name : "nil URLs are skipped" ,
812+ runner : func (_ context.Context , nodes []NodeInfo , _ AddressResolverFunc ) ([]ResolvedAddress , error ) {
813+ out := make ([]ResolvedAddress , len (nodes ))
814+ for i , n := range nodes {
815+ out [i ] = ResolvedAddress {Node : n , URL : nil }
816+ }
817+ return out , nil
818+ },
819+ wantErr : ErrAllResolversFailed ,
820+ },
821+ {
822+ name : "unknown node ID is ignored" ,
823+ runner : func (_ context.Context , nodes []NodeInfo , _ AddressResolverFunc ) ([]ResolvedAddress , error ) {
824+ bogus := NodeInfo {ID : "bogus-id" , Name : "ghost" }
825+ return []ResolvedAddress {
826+ {Node : nodes [0 ], URL : nodes [0 ].URL },
827+ {Node : bogus , URL : nodes [0 ].URL },
828+ }, nil
829+ },
830+ wantNodes : 1 ,
831+ },
832+ }
785833
786- _ , err = tp . getNodesInfo ( ctx )
787- require . ErrorIs ( t , err , context . Canceled )
788- } )
834+ for _ , tt := range runnerEdgeCases {
835+ t . Run ( tt . name , func ( t * testing. T ) {
836+ t . Parallel ( )
789837
790- t .Run ("runner drops all returns ErrAllResolversFailed" , func (t * testing.T ) {
791- t .Parallel ()
838+ ctx := t .Context ()
839+ if tt .makeCtx != nil {
840+ ctx = tt .makeCtx (t )
841+ }
792842
793- tp , err := New (Config {
794- URLs : []* url.URL {testSeedURL (t )},
795- Transport : newResolverTestTransport (t , nodesJSON ),
796- HealthCheck : NoOpHealthCheck ,
797- AddressResolverRunner : func (_ context.Context , _ []NodeInfo , _ AddressResolverFunc ) ([]ResolvedAddress , error ) {
798- return nil , nil
799- },
800- })
801- require .NoError (t , err )
843+ tp , err := New (Config {
844+ URLs : []* url.URL {testSeedURL (t )},
845+ Transport : newResolverTestTransport (t , nodesJSON ),
846+ HealthCheck : NoOpHealthCheck ,
847+ AddressResolverRunner : tt .runner ,
848+ })
849+ require .NoError (t , err )
802850
803- _ , err = tp .getNodesInfo (t .Context ())
804- require .ErrorIs (t , err , ErrAllResolversFailed )
805- })
851+ nodes , err := tp .getNodesInfo (ctx )
852+ if tt .wantErr != nil {
853+ require .ErrorIs (t , err , tt .wantErr )
854+ return
855+ }
856+ require .NoError (t , err )
857+ require .Len (t , nodes , tt .wantNodes )
858+ })
859+ }
806860
807861 t .Run ("runner error propagated" , func (t * testing.T ) {
808862 t .Parallel ()
0 commit comments