@@ -24,6 +24,7 @@ import (
24
24
"testing"
25
25
"time"
26
26
27
+ "github.com/google/go-cmp/cmp"
27
28
"google.golang.org/grpc/attributes"
28
29
"google.golang.org/grpc/balancer"
29
30
"google.golang.org/grpc/connectivity"
@@ -257,3 +258,111 @@ func (s) TestPickFirstLeaf_TFPickerUpdate(t *testing.T) {
257
258
t .Fatalf ("cc.WaitForPickerWithErr(%v) returned error: %v" , newTfErr , err )
258
259
}
259
260
}
261
+
262
+ func (s ) TestPickFirstLeaf_InterleavingIPV4Preffered (t * testing.T ) {
263
+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
264
+ defer cancel ()
265
+ cc := testutils .NewBalancerClientConn (t )
266
+ bal := pickfirstBuilder {}.Build (cc , balancer.BuildOptions {})
267
+ defer bal .Close ()
268
+ ccState := balancer.ClientConnState {
269
+ ResolverState : resolver.State {
270
+ Endpoints : []resolver.Endpoint {
271
+ {Addresses : []resolver.Address {{Addr : "1.1.1.1" }}}, // no port
272
+ {Addresses : []resolver.Address {{Addr : "2.2.2.2:2" }}},
273
+ {Addresses : []resolver.Address {{Addr : "3.3.3.3:3" }}},
274
+ {Addresses : []resolver.Address {{Addr : "4.4.4.4:4" }}},
275
+ {Addresses : []resolver.Address {{Addr : "[0001:0001:0001:0001:0001:0001:0001:0001]:8080" }}}, // ipv6 with port
276
+ {Addresses : []resolver.Address {{Addr : "0002:0002:0002:0002:0002:0002:0002:0002" }}},
277
+ {Addresses : []resolver.Address {{Addr : "0003:0003:0003:0003:0003:0003:0003:0003" }}},
278
+ {Addresses : []resolver.Address {{Addr : "grpc.io:80" }}}, // not an IP.
279
+ },
280
+ },
281
+ }
282
+ if err := bal .UpdateClientConnState (ccState ); err != nil {
283
+ t .Fatalf ("UpdateClientConnState(%v) returned error: %v" , ccState , err )
284
+ }
285
+
286
+ wantAddrs := []resolver.Address {
287
+ {Addr : "1.1.1.1" },
288
+ {Addr : "[0001:0001:0001:0001:0001:0001:0001:0001]:8080" },
289
+ {Addr : "grpc.io:80" },
290
+ {Addr : "2.2.2.2:2" },
291
+ {Addr : "0002:0002:0002:0002:0002:0002:0002:0002" },
292
+ {Addr : "3.3.3.3:3" },
293
+ {Addr : "0003:0003:0003:0003:0003:0003:0003:0003" },
294
+ {Addr : "4.4.4.4:4" },
295
+ }
296
+
297
+ gotAddrs , err := subConnAddresses (ctx , cc , 8 )
298
+ if err != nil {
299
+ t .Fatalf ("%v" , err )
300
+ }
301
+ if diff := cmp .Diff (wantAddrs , gotAddrs ); diff != "" {
302
+ t .Errorf ("subconn creation order mismatch (-want +got):\n %s" , diff )
303
+ }
304
+ }
305
+
306
+ func (s ) TestPickFirstLeaf_InterleavingIPv6Preffered (t * testing.T ) {
307
+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
308
+ defer cancel ()
309
+ cc := testutils .NewBalancerClientConn (t )
310
+ bal := pickfirstBuilder {}.Build (cc , balancer.BuildOptions {})
311
+ defer bal .Close ()
312
+ ccState := balancer.ClientConnState {
313
+ ResolverState : resolver.State {
314
+ Endpoints : []resolver.Endpoint {
315
+ {Addresses : []resolver.Address {{Addr : "[0001:0001:0001:0001:0001:0001:0001:0001]:8080" }}}, // ipv6 with port
316
+ {Addresses : []resolver.Address {{Addr : "1.1.1.1" }}}, // no port
317
+ {Addresses : []resolver.Address {{Addr : "2.2.2.2:2" }}},
318
+ {Addresses : []resolver.Address {{Addr : "3.3.3.3:3" }}},
319
+ {Addresses : []resolver.Address {{Addr : "4.4.4.4:4" }}},
320
+ {Addresses : []resolver.Address {{Addr : "0002:0002:0002:0002:0002:0002:0002:0002" }}},
321
+ {Addresses : []resolver.Address {{Addr : "0003:0003:0003:0003:0003:0003:0003:0003" }}},
322
+ {Addresses : []resolver.Address {{Addr : "grpc.io:80" }}}, // not an IP.
323
+ },
324
+ },
325
+ }
326
+ if err := bal .UpdateClientConnState (ccState ); err != nil {
327
+ t .Fatalf ("UpdateClientConnState(%v) returned error: %v" , ccState , err )
328
+ }
329
+
330
+ wantAddrs := []resolver.Address {
331
+ {Addr : "[0001:0001:0001:0001:0001:0001:0001:0001]:8080" },
332
+ {Addr : "1.1.1.1" },
333
+ {Addr : "grpc.io:80" },
334
+ {Addr : "0002:0002:0002:0002:0002:0002:0002:0002" },
335
+ {Addr : "2.2.2.2:2" },
336
+ {Addr : "0003:0003:0003:0003:0003:0003:0003:0003" },
337
+ {Addr : "3.3.3.3:3" },
338
+ {Addr : "4.4.4.4:4" },
339
+ }
340
+
341
+ gotAddrs , err := subConnAddresses (ctx , cc , 8 )
342
+ if err != nil {
343
+ t .Fatalf ("%v" , err )
344
+ }
345
+ if diff := cmp .Diff (wantAddrs , gotAddrs ); diff != "" {
346
+ t .Errorf ("subconn creation order mismatch (-want +got):\n %s" , diff )
347
+ }
348
+ }
349
+ func subConnAddresses (ctx context.Context , cc * testutils.BalancerClientConn , subConnCount int ) ([]resolver.Address , error ) {
350
+ addresses := []resolver.Address {}
351
+ for i := 0 ; i < subConnCount ; i ++ {
352
+ select {
353
+ case <- ctx .Done ():
354
+ return nil , fmt .Errorf ("Context timed out waiting for SubConn" )
355
+ case sc := <- cc .NewSubConnCh :
356
+ if len (sc .Addresses ) != 1 {
357
+ return nil , fmt .Errorf ("len(SubConn.Addresses) = %d, want 1" , len (sc .Addresses ))
358
+ }
359
+ addresses = append (addresses , sc .Addresses [0 ])
360
+ sc .UpdateState (balancer.SubConnState {ConnectivityState : connectivity .Connecting })
361
+ sc .UpdateState (balancer.SubConnState {
362
+ ConnectivityState : connectivity .TransientFailure ,
363
+ ConnectionError : fmt .Errorf ("test error" ),
364
+ })
365
+ }
366
+ }
367
+ return addresses , nil
368
+ }
0 commit comments