snapshot of https://github.com/grpc/grpc-go.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
This commit is contained in:
147
internal/xds/testutils/balancer_test.go
Normal file
147
internal/xds/testutils/balancer_test.go
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 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 testutils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/internal/testutils"
|
||||
)
|
||||
|
||||
func TestIsRoundRobin(t *testing.T) {
|
||||
var (
|
||||
sc1 = &testutils.TestSubConn{}
|
||||
sc2 = &testutils.TestSubConn{}
|
||||
sc3 = &testutils.TestSubConn{}
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
want []balancer.SubConn
|
||||
got []balancer.SubConn
|
||||
pass bool
|
||||
}{
|
||||
{
|
||||
desc: "0 element",
|
||||
want: []balancer.SubConn{},
|
||||
got: []balancer.SubConn{},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "1 element RR",
|
||||
want: []balancer.SubConn{sc1},
|
||||
got: []balancer.SubConn{sc1, sc1, sc1, sc1},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "1 element not RR",
|
||||
want: []balancer.SubConn{sc1},
|
||||
got: []balancer.SubConn{sc1, sc2, sc1},
|
||||
pass: false,
|
||||
},
|
||||
{
|
||||
desc: "2 elements RR",
|
||||
want: []balancer.SubConn{sc1, sc2},
|
||||
got: []balancer.SubConn{sc1, sc2, sc1, sc2, sc1, sc2},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "2 elements RR different order from want",
|
||||
want: []balancer.SubConn{sc2, sc1},
|
||||
got: []balancer.SubConn{sc1, sc2, sc1, sc2, sc1, sc2},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "2 elements RR not RR, mistake in first iter",
|
||||
want: []balancer.SubConn{sc1, sc2},
|
||||
got: []balancer.SubConn{sc1, sc1, sc1, sc2, sc1, sc2},
|
||||
pass: false,
|
||||
},
|
||||
{
|
||||
desc: "2 elements RR not RR, mistake in second iter",
|
||||
want: []balancer.SubConn{sc1, sc2},
|
||||
got: []balancer.SubConn{sc1, sc2, sc1, sc1, sc1, sc2},
|
||||
pass: false,
|
||||
},
|
||||
{
|
||||
desc: "2 elements weighted RR",
|
||||
want: []balancer.SubConn{sc1, sc1, sc2},
|
||||
got: []balancer.SubConn{sc1, sc1, sc2, sc1, sc1, sc2},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "2 elements weighted RR different order",
|
||||
want: []balancer.SubConn{sc1, sc1, sc2},
|
||||
got: []balancer.SubConn{sc1, sc2, sc1, sc1, sc2, sc1},
|
||||
pass: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "3 elements RR",
|
||||
want: []balancer.SubConn{sc1, sc2, sc3},
|
||||
got: []balancer.SubConn{sc1, sc2, sc3, sc1, sc2, sc3, sc1, sc2, sc3},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "3 elements RR different order",
|
||||
want: []balancer.SubConn{sc1, sc2, sc3},
|
||||
got: []balancer.SubConn{sc3, sc2, sc1, sc3, sc2, sc1},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "3 elements weighted RR",
|
||||
want: []balancer.SubConn{sc1, sc1, sc1, sc2, sc2, sc3},
|
||||
got: []balancer.SubConn{sc1, sc2, sc3, sc1, sc2, sc1, sc1, sc2, sc3, sc1, sc2, sc1},
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
desc: "3 elements weighted RR not RR, mistake in first iter",
|
||||
want: []balancer.SubConn{sc1, sc1, sc1, sc2, sc2, sc3},
|
||||
got: []balancer.SubConn{sc1, sc2, sc1, sc1, sc2, sc1, sc1, sc2, sc3, sc1, sc2, sc1},
|
||||
pass: false,
|
||||
},
|
||||
{
|
||||
desc: "3 elements weighted RR not RR, mistake in second iter",
|
||||
want: []balancer.SubConn{sc1, sc1, sc1, sc2, sc2, sc3},
|
||||
got: []balancer.SubConn{sc1, sc2, sc3, sc1, sc2, sc1, sc1, sc1, sc3, sc1, sc2, sc1},
|
||||
pass: false,
|
||||
},
|
||||
}
|
||||
for _, tC := range testCases {
|
||||
t.Run(tC.desc, func(t *testing.T) {
|
||||
err := testutils.IsRoundRobin(tC.want, (&testClosure{r: tC.got}).next)
|
||||
if err == nil != tC.pass {
|
||||
t.Errorf("want pass %v, want %v, got err %v", tC.pass, tC.want, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// testClosure is a test util for TestIsRoundRobin.
|
||||
type testClosure struct {
|
||||
r []balancer.SubConn
|
||||
i int
|
||||
}
|
||||
|
||||
func (tc *testClosure) next() balancer.SubConn {
|
||||
ret := tc.r[tc.i]
|
||||
tc.i = (tc.i + 1) % len(tc.r)
|
||||
return ret
|
||||
}
|
||||
147
internal/xds/testutils/fakeclient/client.go
Normal file
147
internal/xds/testutils/fakeclient/client.go
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2019 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 fakeclient provides a fake implementation of an xDS client.
|
||||
package fakeclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc/internal/testutils"
|
||||
"google.golang.org/grpc/internal/xds/bootstrap"
|
||||
"google.golang.org/grpc/internal/xds/clients"
|
||||
"google.golang.org/grpc/internal/xds/clients/lrsclient"
|
||||
"google.golang.org/grpc/internal/xds/xdsclient"
|
||||
)
|
||||
|
||||
// Client is a fake implementation of an xds client. It exposes a bunch of
|
||||
// channels to signal the occurrence of various events.
|
||||
type Client struct {
|
||||
// Embed XDSClient so this fake client implements the interface, but it's
|
||||
// never set (it's always nil). This may cause nil panic since not all the
|
||||
// methods are implemented.
|
||||
xdsclient.XDSClient
|
||||
|
||||
name string
|
||||
loadReportCh *testutils.Channel
|
||||
lrsCancelCh *testutils.Channel
|
||||
loadStore *lrsclient.LoadStore
|
||||
bootstrapCfg *bootstrap.Config
|
||||
}
|
||||
|
||||
// ReportLoadArgs wraps the arguments passed to ReportLoad.
|
||||
type ReportLoadArgs struct {
|
||||
// Server is the name of the server to which the load is reported.
|
||||
Server *bootstrap.ServerConfig
|
||||
}
|
||||
|
||||
type transportBuilder struct {
|
||||
}
|
||||
|
||||
func (*transportBuilder) Build(clients.ServerIdentifier) (clients.Transport, error) {
|
||||
return &transport{}, nil
|
||||
}
|
||||
|
||||
type transport struct {
|
||||
}
|
||||
|
||||
func (*transport) NewStream(context.Context, string) (clients.Stream, error) {
|
||||
return &stream{}, nil
|
||||
}
|
||||
|
||||
func (*transport) Close() {
|
||||
}
|
||||
|
||||
type stream struct {
|
||||
}
|
||||
|
||||
func (*stream) Send([]byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*stream) Recv() ([]byte, error) {
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
// ReportLoad starts reporting load about clusterName to server.
|
||||
func (xdsC *Client) ReportLoad(server *bootstrap.ServerConfig) (loadStore *lrsclient.LoadStore, cancel func(context.Context)) {
|
||||
lrsClient, _ := lrsclient.New(lrsclient.Config{Node: clients.Node{ID: "fake-node-id"}, TransportBuilder: &transportBuilder{}})
|
||||
xdsC.loadStore, _ = lrsClient.ReportLoad(clients.ServerIdentifier{ServerURI: server.ServerURI()})
|
||||
|
||||
xdsC.loadReportCh.Send(ReportLoadArgs{Server: server})
|
||||
|
||||
return xdsC.loadStore, func(ctx context.Context) {
|
||||
xdsC.loadStore.Stop(ctx)
|
||||
xdsC.lrsCancelCh.Send(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCancelReportLoad waits for a load report to be cancelled and returns
|
||||
// context.DeadlineExceeded otherwise.
|
||||
func (xdsC *Client) WaitForCancelReportLoad(ctx context.Context) error {
|
||||
_, err := xdsC.lrsCancelCh.Receive(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadStore returns the underlying load data store.
|
||||
func (xdsC *Client) LoadStore() *lrsclient.LoadStore {
|
||||
return xdsC.loadStore
|
||||
}
|
||||
|
||||
// WaitForReportLoad waits for ReportLoad to be invoked on this client and
|
||||
// returns the arguments passed to it.
|
||||
func (xdsC *Client) WaitForReportLoad(ctx context.Context) (ReportLoadArgs, error) {
|
||||
val, err := xdsC.loadReportCh.Receive(ctx)
|
||||
if err != nil {
|
||||
return ReportLoadArgs{}, err
|
||||
}
|
||||
return val.(ReportLoadArgs), nil
|
||||
}
|
||||
|
||||
// BootstrapConfig returns the bootstrap config.
|
||||
func (xdsC *Client) BootstrapConfig() *bootstrap.Config {
|
||||
return xdsC.bootstrapCfg
|
||||
}
|
||||
|
||||
// SetBootstrapConfig updates the bootstrap config.
|
||||
func (xdsC *Client) SetBootstrapConfig(cfg *bootstrap.Config) {
|
||||
xdsC.bootstrapCfg = cfg
|
||||
}
|
||||
|
||||
// Name returns the name of the xds client.
|
||||
func (xdsC *Client) Name() string {
|
||||
return xdsC.name
|
||||
}
|
||||
|
||||
// NewClient returns a new fake xds client.
|
||||
func NewClient() *Client {
|
||||
return NewClientWithName("")
|
||||
}
|
||||
|
||||
// NewClientWithName returns a new fake xds client with the provided name. This
|
||||
// is used in cases where multiple clients are created in the tests and we need
|
||||
// to make sure the client is created for the expected balancer name.
|
||||
func NewClientWithName(name string) *Client {
|
||||
return &Client{
|
||||
name: name,
|
||||
loadReportCh: testutils.NewChannel(),
|
||||
lrsCancelCh: testutils.NewChannel(),
|
||||
bootstrapCfg: &bootstrap.Config{},
|
||||
}
|
||||
}
|
||||
83
internal/xds/testutils/resource_watcher.go
Normal file
83
internal/xds/testutils/resource_watcher.go
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2023 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 testutils
|
||||
|
||||
import "google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
|
||||
|
||||
// TestResourceWatcher implements the xdsresource.ResourceWatcher interface,
|
||||
// used to receive updates on watches registered with the xDS client, when using
|
||||
// the resource-type agnostic WatchResource API.
|
||||
//
|
||||
// Tests can use the channels provided by this type to get access to updates and
|
||||
// errors sent by the xDS client.
|
||||
type TestResourceWatcher struct {
|
||||
// UpdateCh is the channel on which xDS client updates are delivered.
|
||||
UpdateCh chan *xdsresource.ResourceData
|
||||
// AmbientErrorCh is the channel on which ambient errors from the xDS
|
||||
// client are delivered.
|
||||
AmbientErrorCh chan error
|
||||
// ResourceErrorCh is the channel on which resource errors from the xDS
|
||||
// client are delivered.
|
||||
ResourceErrorCh chan struct{}
|
||||
}
|
||||
|
||||
// ResourceChanged is invoked by the xDS client to report the latest update.
|
||||
func (w *TestResourceWatcher) ResourceChanged(data xdsresource.ResourceData, onDone func()) {
|
||||
defer onDone()
|
||||
select {
|
||||
case <-w.UpdateCh:
|
||||
default:
|
||||
}
|
||||
w.UpdateCh <- &data
|
||||
|
||||
}
|
||||
|
||||
// ResourceError is invoked by the xDS client to report the latest error to
|
||||
// stop watching the resource.
|
||||
func (w *TestResourceWatcher) ResourceError(err error, onDone func()) {
|
||||
defer onDone()
|
||||
select {
|
||||
case <-w.ResourceErrorCh:
|
||||
case <-w.AmbientErrorCh:
|
||||
default:
|
||||
}
|
||||
w.AmbientErrorCh <- err
|
||||
w.ResourceErrorCh <- struct{}{}
|
||||
}
|
||||
|
||||
// AmbientError is invoked by the xDS client to report the latest ambient
|
||||
// error.
|
||||
func (w *TestResourceWatcher) AmbientError(err error, onDone func()) {
|
||||
defer onDone()
|
||||
select {
|
||||
case <-w.AmbientErrorCh:
|
||||
default:
|
||||
}
|
||||
w.AmbientErrorCh <- err
|
||||
}
|
||||
|
||||
// NewTestResourceWatcher returns a TestResourceWatcher to watch for resources
|
||||
// via the xDS client.
|
||||
func NewTestResourceWatcher() *TestResourceWatcher {
|
||||
return &TestResourceWatcher{
|
||||
UpdateCh: make(chan *xdsresource.ResourceData, 1),
|
||||
AmbientErrorCh: make(chan error, 1),
|
||||
ResourceErrorCh: make(chan struct{}, 1),
|
||||
}
|
||||
}
|
||||
51
internal/xds/testutils/testutils.go
Normal file
51
internal/xds/testutils/testutils.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2021 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 testutils provides utility types, for use in xds tests.
|
||||
package testutils
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
|
||||
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource/version"
|
||||
)
|
||||
|
||||
// BuildResourceName returns the resource name in the format of an xdstp://
|
||||
// resource.
|
||||
func BuildResourceName(typeName, auth, id string, ctxParams map[string]string) string {
|
||||
var typS string
|
||||
switch typeName {
|
||||
case xdsresource.ListenerResourceTypeName:
|
||||
typS = version.V3ListenerType
|
||||
case xdsresource.RouteConfigTypeName:
|
||||
typS = version.V3RouteConfigType
|
||||
case xdsresource.ClusterResourceTypeName:
|
||||
typS = version.V3ClusterType
|
||||
case xdsresource.EndpointsResourceTypeName:
|
||||
typS = version.V3EndpointsType
|
||||
default:
|
||||
// If the name doesn't match any of the standard resources fallback
|
||||
// to the type name.
|
||||
typS = typeName
|
||||
}
|
||||
return (&xdsresource.Name{
|
||||
Scheme: "xdstp",
|
||||
Authority: auth,
|
||||
Type: typS,
|
||||
ID: id,
|
||||
ContextParams: ctxParams,
|
||||
}).String()
|
||||
}
|
||||
Reference in New Issue
Block a user