Skip to content

Commit

Permalink
pickfirst: Move var for mocking the shuffle func from internal/intern…
Browse files Browse the repository at this point in the history
…al to pickfirst/internal (#7698)
  • Loading branch information
arjan-bal authored Oct 9, 2024
1 parent d9d8f34 commit b8ee37d
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 16 deletions.
24 changes: 24 additions & 0 deletions balancer/pickfirst/internal/internal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2024 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Package internal contains code internal to the pickfirst package.
package internal

import "math/rand"

// RandShuffle pseudo-randomizes the order of addresses.
var RandShuffle = rand.Shuffle
5 changes: 2 additions & 3 deletions balancer/pickfirst/pickfirst.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import (
"math/rand"

"google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/pickfirst/internal"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal"
internalgrpclog "google.golang.org/grpc/internal/grpclog"
"google.golang.org/grpc/internal/pretty"
"google.golang.org/grpc/resolver"
Expand All @@ -37,7 +37,6 @@ import (

func init() {
balancer.Register(pickfirstBuilder{})
internal.ShuffleAddressListForTesting = func(n int, swap func(i, j int)) { rand.Shuffle(n, swap) }
}

var logger = grpclog.Component("pick-first-lb")
Expand Down Expand Up @@ -143,7 +142,7 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState
// within each endpoint. - A61
if cfg.ShuffleAddressList {
endpoints = append([]resolver.Endpoint{}, endpoints...)
internal.ShuffleAddressListForTesting.(func(int, func(int, int)))(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] })
internal.RandShuffle(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] })
}

// "Flatten the list by concatenating the ordered list of addresses for each
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
*/

package test
package pickfirst_test

import (
"context"
Expand All @@ -28,11 +28,13 @@ import (

"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
pfinternal "google.golang.org/grpc/balancer/pickfirst/internal"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/internal/grpctest"
"google.golang.org/grpc/internal/stubserver"
"google.golang.org/grpc/internal/testutils"
"google.golang.org/grpc/internal/testutils/pickfirst"
Expand All @@ -45,7 +47,38 @@ import (
testpb "google.golang.org/grpc/interop/grpc_testing"
)

const pickFirstServiceConfig = `{"loadBalancingConfig": [{"pick_first":{}}]}`
const (
pickFirstServiceConfig = `{"loadBalancingConfig": [{"pick_first":{}}]}`
// Default timeout for tests in this package.
defaultTestTimeout = 10 * time.Second
// Default short timeout, to be used when waiting for events which are not
// expected to happen.
defaultTestShortTimeout = 100 * time.Millisecond
)

func init() {
channelz.TurnOn()
}

type s struct {
grpctest.Tester
}

func Test(t *testing.T) {
grpctest.RunSubTests(t, s{})
}

// parseServiceConfig is a test helper which uses the manual resolver to parse
// the given service config. It calls t.Fatal() if service config parsing fails.
func parseServiceConfig(t *testing.T, r *manual.Resolver, sc string) *serviceconfig.ParseResult {
t.Helper()

scpr := r.CC.ParseServiceConfig(sc)
if scpr.Err != nil {
t.Fatalf("Failed to parse service config %q: %v", sc, scpr.Err)
}
return scpr
}

// setupPickFirst performs steps required for pick_first tests. It starts a
// bunch of backends exporting the TestService, creates a ClientConn to them
Expand Down Expand Up @@ -377,16 +410,15 @@ func (s) TestPickFirst_ShuffleAddressList(t *testing.T) {
const serviceConfig = `{"loadBalancingConfig": [{"pick_first":{ "shuffleAddressList": true }}]}`

// Install a shuffler that always reverses two entries.
origShuf := internal.ShuffleAddressListForTesting
defer func() { internal.ShuffleAddressListForTesting = origShuf }()
internal.ShuffleAddressListForTesting = func(n int, f func(int, int)) {
origShuf := pfinternal.RandShuffle
defer func() { pfinternal.RandShuffle = origShuf }()
pfinternal.RandShuffle = func(n int, f func(int, int)) {
if n != 2 {
t.Errorf("Shuffle called with n=%v; want 2", n)
return
}
f(0, 1) // reverse the two addresses
}

// Set up our backends.
cc, r, backends := setupPickFirst(t, 2)
addrs := stubBackendsToResolverAddrs(backends)
Expand Down Expand Up @@ -434,9 +466,9 @@ func (s) TestPickFirst_ShuffleAddressList(t *testing.T) {
// Test config parsing with the env var turned on and off for various scenarios.
func (s) TestPickFirst_ParseConfig_Success(t *testing.T) {
// Install a shuffler that always reverses two entries.
origShuf := internal.ShuffleAddressListForTesting
defer func() { internal.ShuffleAddressListForTesting = origShuf }()
internal.ShuffleAddressListForTesting = func(n int, f func(int, int)) {
origShuf := pfinternal.RandShuffle
defer func() { pfinternal.RandShuffle = origShuf }()
pfinternal.RandShuffle = func(n int, f func(int, int)) {
if n != 2 {
t.Errorf("Shuffle called with n=%v; want 2", n)
return
Expand Down
4 changes: 0 additions & 4 deletions internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,6 @@ var (
// default resolver scheme.
UserSetDefaultScheme = false

// ShuffleAddressListForTesting pseudo-randomizes the order of addresses. n
// is the number of elements. swap swaps the elements with indexes i and j.
ShuffleAddressListForTesting any // func(n int, swap func(i, j int))

// ConnectedAddress returns the connected address for a SubConnState. The
// address is only valid if the state is READY.
ConnectedAddress any // func (scs SubConnState) resolver.Address
Expand Down
11 changes: 11 additions & 0 deletions test/balancer_switching_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,24 @@ const (
loadBalancedServicePort = 443
wantGRPCLBTraceDesc = `Channel switches to new LB policy "grpclb"`
wantRoundRobinTraceDesc = `Channel switches to new LB policy "round_robin"`
pickFirstServiceConfig = `{"loadBalancingConfig": [{"pick_first":{}}]}`

// This is the number of stub backends set up at the start of each test. The
// first backend is used for the "grpclb" policy and the rest are used for
// other LB policies to test balancer switching.
backendCount = 3
)

// stubBackendsToResolverAddrs converts from a set of stub server backends to
// resolver addresses. Useful when pushing addresses to the manual resolver.
func stubBackendsToResolverAddrs(backends []*stubserver.StubServer) []resolver.Address {
addrs := make([]resolver.Address, len(backends))
for i, backend := range backends {
addrs[i] = resolver.Address{Addr: backend.Address}
}
return addrs
}

// setupBackendsAndFakeGRPCLB sets up backendCount number of stub server
// backends and a fake grpclb server for tests which exercise balancer switch
// scenarios involving grpclb.
Expand Down

0 comments on commit b8ee37d

Please sign in to comment.