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
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
Testing / tests (arm, latest) (push) Waiting to run
Testing / vet-proto (push) Failing after 1s
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
Stale bot / stale (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (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
Testing / tests (arm, latest) (push) Waiting to run
Testing / vet-proto (push) Failing after 1s
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
Stale bot / stale (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
This commit is contained in:
179
internal/xds/test/e2e/e2e_utils.go
Normal file
179
internal/xds/test/e2e/e2e_utils.go
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
*
|
||||
* 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 e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cespare/xxhash/v2"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
"google.golang.org/grpc/internal/xds/clients"
|
||||
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
func verifySubConnStates(t *testing.T, scs []*channelzpb.Subchannel, want map[channelzpb.ChannelConnectivityState_State]int) {
|
||||
t.Helper()
|
||||
var scStatsCount = map[channelzpb.ChannelConnectivityState_State]int{}
|
||||
for _, sc := range scs {
|
||||
scStatsCount[sc.Data.State.State]++
|
||||
}
|
||||
if diff := cmp.Diff(scStatsCount, want); diff != "" {
|
||||
t.Fatalf("got unexpected number of subchannels in state Ready, %v, scs: %v", diff, scs)
|
||||
}
|
||||
}
|
||||
|
||||
// This function determines the stable, canonical order for any two
|
||||
// resolver.Endpoint structs.
|
||||
func lessEndpoint(a, b resolver.Endpoint) bool {
|
||||
return getHash(a) < getHash(b)
|
||||
}
|
||||
|
||||
func getHash(e resolver.Endpoint) uint64 {
|
||||
h := xxhash.New()
|
||||
|
||||
// We iterate through all addresses to ensure the hash represents
|
||||
// the full endpoint identity.
|
||||
for _, addr := range e.Addresses {
|
||||
h.Write([]byte(addr.Addr))
|
||||
h.Write([]byte(addr.ServerName))
|
||||
}
|
||||
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
// VerifyXDSConfig waits for an update on the xdsCh channel or an error on the
|
||||
// errCh channel, and verifies that the received XDSConfig matches the expected
|
||||
// XDS configuration.
|
||||
func VerifyXDSConfig(ctx context.Context, xdsCh chan *xdsresource.XDSConfig, errCh chan error, want *xdsresource.XDSConfig) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return fmt.Errorf("timeout waiting for update from dependency manager")
|
||||
case update := <-xdsCh:
|
||||
if err := CompareXDSConfig(update, want); err != nil {
|
||||
return err
|
||||
}
|
||||
case err := <-errCh:
|
||||
return fmt.Errorf("received unexpected error from dependency manager: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompareXDSConfig compares two XDSConfig structs and returns an error if they
|
||||
// do not match.
|
||||
func CompareXDSConfig(gotXDSConfig, wantXDSConfig *xdsresource.XDSConfig) error {
|
||||
cmpOpts := []cmp.Option{
|
||||
cmpopts.EquateEmpty(),
|
||||
cmpopts.IgnoreFields(xdsresource.HTTPFilter{}, "Filter", "Config"),
|
||||
cmpopts.IgnoreFields(xdsresource.ListenerUpdate{}, "Raw"),
|
||||
cmpopts.IgnoreFields(xdsresource.RouteConfigUpdate{}, "Raw"),
|
||||
cmpopts.IgnoreFields(xdsresource.ClusterUpdate{}, "Raw", "LBPolicy", "TelemetryLabels"),
|
||||
cmpopts.IgnoreFields(xdsresource.EndpointsUpdate{}, "Raw"),
|
||||
// Used for EndpointConfig.ResolutionNote and ClusterResult.Err fields.
|
||||
cmp.Transformer("ErrorsToString", func(in error) string {
|
||||
if in == nil {
|
||||
return "" // Treat nil as an empty string
|
||||
}
|
||||
s := in.Error()
|
||||
|
||||
// Replace all sequences of whitespace (including newlines and
|
||||
// tabs) with a single standard space.
|
||||
s = regexp.MustCompile(`\s+`).ReplaceAllString(s, " ")
|
||||
|
||||
// Trim any leading/trailing space that might be left over and
|
||||
// return error as string.
|
||||
return strings.TrimSpace(s)
|
||||
}),
|
||||
cmpopts.SortSlices(lessEndpoint),
|
||||
}
|
||||
if diff := cmp.Diff(gotXDSConfig, wantXDSConfig, cmpOpts...); diff != "" {
|
||||
return fmt.Errorf("received unexpected update from dependency manager. Diff (-got +want):\n%v", diff)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeXDSConfig creates a mock XDSConfig with a standard structure containing
|
||||
// a Listener, RouteConfig, VirtualHost, and a single EDS Cluster, populated
|
||||
// with the provided parameters.
|
||||
func MakeXDSConfig(servicename, routeConfigName, clusterName, edsServiceName, addr string) *xdsresource.XDSConfig {
|
||||
prefix := "/"
|
||||
return &xdsresource.XDSConfig{
|
||||
Listener: &xdsresource.ListenerUpdate{
|
||||
APIListener: &xdsresource.HTTPConnectionManagerConfig{
|
||||
RouteConfigName: routeConfigName,
|
||||
HTTPFilters: []xdsresource.HTTPFilter{{Name: "router"}},
|
||||
},
|
||||
},
|
||||
RouteConfig: &xdsresource.RouteConfigUpdate{
|
||||
VirtualHosts: []*xdsresource.VirtualHost{
|
||||
{
|
||||
Domains: []string{servicename},
|
||||
Routes: []*xdsresource.Route{{
|
||||
Prefix: &prefix,
|
||||
WeightedClusters: []xdsresource.WeightedCluster{{Name: clusterName, Weight: 100}},
|
||||
ActionType: xdsresource.RouteActionRoute,
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
VirtualHost: &xdsresource.VirtualHost{
|
||||
Domains: []string{servicename},
|
||||
Routes: []*xdsresource.Route{{
|
||||
Prefix: &prefix,
|
||||
WeightedClusters: []xdsresource.WeightedCluster{{Name: clusterName, Weight: 100}},
|
||||
ActionType: xdsresource.RouteActionRoute},
|
||||
},
|
||||
},
|
||||
Clusters: map[string]*xdsresource.ClusterResult{
|
||||
clusterName: {
|
||||
Config: xdsresource.ClusterConfig{Cluster: &xdsresource.ClusterUpdate{
|
||||
ClusterType: xdsresource.ClusterTypeEDS,
|
||||
ClusterName: clusterName,
|
||||
EDSServiceName: edsServiceName,
|
||||
},
|
||||
EndpointConfig: &xdsresource.EndpointConfig{
|
||||
EDSUpdate: &xdsresource.EndpointsUpdate{
|
||||
Localities: []xdsresource.Locality{
|
||||
{ID: clients.Locality{
|
||||
Region: "region-1",
|
||||
Zone: "zone-1",
|
||||
SubZone: "subzone-1",
|
||||
},
|
||||
Endpoints: []xdsresource.Endpoint{
|
||||
{
|
||||
ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: addr}}},
|
||||
HealthStatus: xdsresource.EndpointHealthStatusUnknown,
|
||||
Weight: 1,
|
||||
},
|
||||
},
|
||||
Weight: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user