@@ -41,6 +41,7 @@ import (
41
41
"google.golang.org/grpc/internal/testutils"
42
42
"google.golang.org/grpc/internal/testutils/pickfirst"
43
43
"google.golang.org/grpc/internal/testutils/stats"
44
+ "google.golang.org/grpc/metadata"
44
45
"google.golang.org/grpc/resolver"
45
46
"google.golang.org/grpc/resolver/manual"
46
47
"google.golang.org/grpc/status"
@@ -1424,6 +1425,85 @@ func (s) TestPickFirstLeaf_HealthUpdates(t *testing.T) {
1424
1425
testutils .AwaitState (ctx , t , cc , connectivity .TransientFailure )
1425
1426
}
1426
1427
1428
+ // Tests the case where an address update received by the pick_first LB policy
1429
+ // differs in metadata which should be ignored by the LB policy. In this case,
1430
+ // the test verifies that new connections are not created when the address
1431
+ // update only changes the metadata.
1432
+ func (s ) TestPickFirstLeaf_AddressUpdateWithMetadata (t * testing.T ) {
1433
+ dialer := testutils .NewBlockingDialer ()
1434
+ dopts := []grpc.DialOption {
1435
+ grpc .WithDefaultServiceConfig (fmt .Sprintf (`{"loadBalancingConfig": [{"%s":{}}]}` , pickfirstleaf .Name )),
1436
+ grpc .WithContextDialer (dialer .DialContext ),
1437
+ }
1438
+ cc , r , backends := setupPickFirstLeaf (t , 2 , dopts ... )
1439
+
1440
+ // Add a metadata to the addresses before pushing them to the pick_first LB
1441
+ // policy through the manual resolver.
1442
+ addrs := backends .resolverAddrs ()
1443
+ for i := range addrs {
1444
+ addrs [i ].Metadata = & metadata.MD {
1445
+ "test-metadata-1" : []string {fmt .Sprintf ("%d" , i )},
1446
+ }
1447
+ }
1448
+ r .UpdateState (resolver.State {Addresses : addrs })
1449
+
1450
+ // Ensure that RPCs succeed to the expected backend.
1451
+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
1452
+ defer cancel ()
1453
+ if err := pickfirst .CheckRPCsToBackend (ctx , cc , addrs [0 ]); err != nil {
1454
+ t .Fatal (err )
1455
+ }
1456
+
1457
+ // Create holds for each backend. This will be used to verify the connection
1458
+ // is not re-established.
1459
+ holds := backends .holds (dialer )
1460
+
1461
+ // Add metadata to the addresses before pushing them to the pick_first LB
1462
+ // policy through the manual resolver. Leave the order of the addresses
1463
+ // unchanged.
1464
+ for i := range addrs {
1465
+ addrs [i ].Metadata = & metadata.MD {
1466
+ "test-metadata-2" : []string {fmt .Sprintf ("%d" , i )},
1467
+ }
1468
+ }
1469
+ r .UpdateState (resolver.State {Addresses : addrs })
1470
+
1471
+ // Ensure that no new connection is established.
1472
+ for i := range holds {
1473
+ sCtx , sCancel := context .WithTimeout (ctx , defaultTestShortTimeout )
1474
+ defer sCancel ()
1475
+ if holds [i ].Wait (sCtx ) {
1476
+ t .Fatalf ("Unexpected connection attempt to backend: %s" , addrs [i ])
1477
+ }
1478
+ }
1479
+
1480
+ if err := pickfirst .CheckRPCsToBackend (ctx , cc , addrs [0 ]); err != nil {
1481
+ t .Fatal (err )
1482
+ }
1483
+
1484
+ // Add metadata to the addresses before pushing them to the pick_first LB
1485
+ // policy through the manual resolver. Reverse of the order of addresses.
1486
+ for i := range addrs {
1487
+ addrs [i ].Metadata = & metadata.MD {
1488
+ "test-metadata-3" : []string {fmt .Sprintf ("%d" , i )},
1489
+ }
1490
+ }
1491
+ addrs [0 ], addrs [1 ] = addrs [1 ], addrs [0 ]
1492
+ r .UpdateState (resolver.State {Addresses : addrs })
1493
+
1494
+ // Ensure that no new connection is established.
1495
+ for i := range holds {
1496
+ sCtx , sCancel := context .WithTimeout (ctx , defaultTestShortTimeout )
1497
+ defer sCancel ()
1498
+ if holds [i ].Wait (sCtx ) {
1499
+ t .Fatalf ("Unexpected connection attempt to backend: %s" , addrs [i ])
1500
+ }
1501
+ }
1502
+ if err := pickfirst .CheckRPCsToBackend (ctx , cc , addrs [1 ]); err != nil {
1503
+ t .Fatal (err )
1504
+ }
1505
+ }
1506
+
1427
1507
// healthListenerCapturingCCWrapper is used to capture the health listener so
1428
1508
// that health updates can be mocked for testing.
1429
1509
type healthListenerCapturingCCWrapper struct {
0 commit comments