@@ -39,7 +39,9 @@ import (
3939 "google.golang.org/grpc/credentials/insecure"
4040 "google.golang.org/grpc/internal"
4141 "google.golang.org/grpc/internal/balancer/stub"
42+ "google.golang.org/grpc/internal/balancer/weight"
4243 "google.golang.org/grpc/internal/channelz"
44+ "google.golang.org/grpc/internal/envconfig"
4345 "google.golang.org/grpc/internal/grpcsync"
4446 "google.golang.org/grpc/internal/grpctest"
4547 "google.golang.org/grpc/internal/stubserver"
@@ -425,6 +427,8 @@ func (s) TestPickFirst_StickyTransientFailure(t *testing.T) {
425427
426428// Tests the PF LB policy with shuffling enabled.
427429func (s ) TestPickFirst_ShuffleAddressList (t * testing.T ) {
430+ testutils .SetEnvConfig (t , & envconfig .PickFirstWeightedShuffling , false )
431+
428432 const serviceConfig = `{"loadBalancingConfig": [{"pick_first":{ "shuffleAddressList": true }}]}`
429433
430434 // Install a shuffler that always reverses two entries.
@@ -485,6 +489,8 @@ func (s) TestPickFirst_ShuffleAddressList(t *testing.T) {
485489// Endpoints field in the resolver update to test the shuffling of the
486490// Addresses.
487491func (s ) TestPickFirst_ShuffleAddressListNoEndpoints (t * testing.T ) {
492+ testutils .SetEnvConfig (t , & envconfig .PickFirstWeightedShuffling , false )
493+
488494 // Install a shuffler that always reverses two entries.
489495 origShuf := pfinternal .RandShuffle
490496 defer func () { pfinternal .RandShuffle = origShuf }()
@@ -560,8 +566,73 @@ func (s) TestPickFirst_ShuffleAddressListNoEndpoints(t *testing.T) {
560566 }
561567}
562568
569+ // Tests the PF LB policy with weighted shuffling enabled.
570+ func (s ) TestPickFirst_ShuffleAddressList_WeightedShuffling (t * testing.T ) {
571+ testutils .SetEnvConfig (t , & envconfig .PickFirstWeightedShuffling , true )
572+
573+ const serviceConfig = `{"loadBalancingConfig": [{"pick_first":{ "shuffleAddressList": true }}]}`
574+
575+ // Install a rand func that returns a constant value. The test sets up three
576+ // endpoints with increasing weights. This means that in the weighted
577+ // shuffling algorithm, the endpoints will end up with increasing values for
578+ // their keys. And since the algorithm sorts in descending order, the last
579+ // endpoint should be the one that would get picked.
580+ origRand := pfinternal .RandFloat64
581+ defer func () { pfinternal .RandFloat64 = origRand }()
582+ pfinternal .RandFloat64 = func () float64 {
583+ return 0.5
584+ }
585+
586+ // Set up our backends.
587+ cc , r , backends := setupPickFirst (t , 3 )
588+ addrs := stubBackendsToResolverAddrs (backends )
589+
590+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
591+ defer cancel ()
592+
593+ // Create endpoints for the above backends with increasing weights.
594+ ep1 := resolver.Endpoint {Addresses : []resolver.Address {addrs [0 ]}}
595+ ep1 = weight .Set (ep1 , weight.EndpointInfo {Weight : 357913941 }) // Normalized weight of 1/6
596+ ep2 := resolver.Endpoint {Addresses : []resolver.Address {addrs [1 ]}}
597+ ep2 = weight .Set (ep2 , weight.EndpointInfo {Weight : 715827882 }) // Normalized weight of 2/6
598+ ep3 := resolver.Endpoint {Addresses : []resolver.Address {addrs [2 ]}}
599+ ep3 = weight .Set (ep3 , weight.EndpointInfo {Weight : 1073741824 }) // Normalized weight of 3/6
600+
601+ // Push an update with all addresses and shuffling disabled. We should
602+ // connect to backend 0.
603+ r .UpdateState (resolver.State {Endpoints : []resolver.Endpoint {ep1 , ep2 , ep3 }})
604+ if err := pickfirst .CheckRPCsToBackend (ctx , cc , addrs [0 ]); err != nil {
605+ t .Fatal (err )
606+ }
607+
608+ // Send a config with shuffling enabled. This will reverse the addresses,
609+ // but the channel should still be connected to backend 0.
610+ shufState := resolver.State {
611+ ServiceConfig : parseServiceConfig (t , r , serviceConfig ),
612+ Endpoints : []resolver.Endpoint {ep1 , ep2 , ep3 },
613+ }
614+ r .UpdateState (shufState )
615+ if err := pickfirst .CheckRPCsToBackend (ctx , cc , addrs [0 ]); err != nil {
616+ t .Fatal (err )
617+ }
618+
619+ // Send a resolver update with no addresses. This should push the channel
620+ // into TransientFailure.
621+ r .UpdateState (resolver.State {})
622+ testutils .AwaitState (ctx , t , cc , connectivity .TransientFailure )
623+
624+ // Send the same config as last time with shuffling enabled. Since we are
625+ // not connected to backend 0, we should connect to backend 2.
626+ r .UpdateState (shufState )
627+ if err := pickfirst .CheckRPCsToBackend (ctx , cc , addrs [2 ]); err != nil {
628+ t .Fatal (err )
629+ }
630+ }
631+
563632// Test config parsing with the env var turned on and off for various scenarios.
564633func (s ) TestPickFirst_ParseConfig_Success (t * testing.T ) {
634+ testutils .SetEnvConfig (t , & envconfig .PickFirstWeightedShuffling , false )
635+
565636 // Install a shuffler that always reverses two entries.
566637 origShuf := pfinternal .RandShuffle
567638 defer func () { pfinternal .RandShuffle = origShuf }()
0 commit comments