gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/xds/internal/xdsclient/controller/v2_cds_test.go (about) 1 /* 2 * 3 * Copyright 2019 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package controller 20 21 import ( 22 "testing" 23 "time" 24 25 xdspb "gitee.com/ks-custle/core-gm/go-control-plane/envoy/api/v2" 26 corepb "gitee.com/ks-custle/core-gm/go-control-plane/envoy/api/v2/core" 27 "gitee.com/ks-custle/core-gm/grpc/internal/testutils" 28 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource" 29 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource/version" 30 anypb "github.com/golang/protobuf/ptypes/any" 31 "github.com/google/go-cmp/cmp/cmpopts" 32 ) 33 34 const ( 35 serviceName1 = "foo-service" 36 serviceName2 = "bar-service" 37 ) 38 39 var ( 40 badlyMarshaledCDSResponse = &xdspb.DiscoveryResponse{ 41 Resources: []*anypb.Any{ 42 { 43 TypeUrl: version.V2ClusterURL, 44 Value: []byte{1, 2, 3, 4}, 45 }, 46 }, 47 TypeUrl: version.V2ClusterURL, 48 } 49 goodCluster1 = &xdspb.Cluster{ 50 Name: goodClusterName1, 51 ClusterDiscoveryType: &xdspb.Cluster_Type{Type: xdspb.Cluster_EDS}, 52 EdsClusterConfig: &xdspb.Cluster_EdsClusterConfig{ 53 EdsConfig: &corepb.ConfigSource{ 54 ConfigSourceSpecifier: &corepb.ConfigSource_Ads{ 55 Ads: &corepb.AggregatedConfigSource{}, 56 }, 57 }, 58 ServiceName: serviceName1, 59 }, 60 LbPolicy: xdspb.Cluster_ROUND_ROBIN, 61 LrsServer: &corepb.ConfigSource{ 62 ConfigSourceSpecifier: &corepb.ConfigSource_Self{ 63 Self: &corepb.SelfConfigSource{}, 64 }, 65 }, 66 } 67 marshaledCluster1 = testutils.MarshalAny(goodCluster1) 68 goodCluster2 = &xdspb.Cluster{ 69 Name: goodClusterName2, 70 ClusterDiscoveryType: &xdspb.Cluster_Type{Type: xdspb.Cluster_EDS}, 71 EdsClusterConfig: &xdspb.Cluster_EdsClusterConfig{ 72 EdsConfig: &corepb.ConfigSource{ 73 ConfigSourceSpecifier: &corepb.ConfigSource_Ads{ 74 Ads: &corepb.AggregatedConfigSource{}, 75 }, 76 }, 77 ServiceName: serviceName2, 78 }, 79 LbPolicy: xdspb.Cluster_ROUND_ROBIN, 80 } 81 marshaledCluster2 = testutils.MarshalAny(goodCluster2) 82 goodCDSResponse1 = &xdspb.DiscoveryResponse{ 83 Resources: []*anypb.Any{ 84 marshaledCluster1, 85 }, 86 TypeUrl: version.V2ClusterURL, 87 } 88 goodCDSResponse2 = &xdspb.DiscoveryResponse{ 89 Resources: []*anypb.Any{ 90 marshaledCluster2, 91 }, 92 TypeUrl: version.V2ClusterURL, 93 } 94 ) 95 96 // TestCDSHandleResponse starts a fake xDS server, makes a ClientConn to it, 97 // and creates a v2Client using it. Then, it registers a CDS watcher and tests 98 // different CDS responses. 99 func (s) TestCDSHandleResponse(t *testing.T) { 100 tests := []struct { 101 name string 102 cdsResponse *xdspb.DiscoveryResponse 103 wantErr bool 104 wantUpdate map[string]xdsresource.ClusterUpdateErrTuple 105 wantUpdateMD xdsresource.UpdateMetadata 106 wantUpdateErr bool 107 }{ 108 // Badly marshaled CDS response. 109 { 110 name: "badly-marshaled-response", 111 cdsResponse: badlyMarshaledCDSResponse, 112 wantErr: true, 113 wantUpdate: nil, 114 wantUpdateMD: xdsresource.UpdateMetadata{ 115 Status: xdsresource.ServiceStatusNACKed, 116 ErrState: &xdsresource.UpdateErrorMetadata{ 117 Err: cmpopts.AnyError, 118 }, 119 }, 120 wantUpdateErr: false, 121 }, 122 // Response contains one good cluster we are not interested in. 123 { 124 name: "one-uninteresting-cluster", 125 cdsResponse: goodCDSResponse2, 126 wantErr: false, 127 wantUpdate: map[string]xdsresource.ClusterUpdateErrTuple{ 128 goodClusterName2: {Update: xdsresource.ClusterUpdate{ClusterName: goodClusterName2, EDSServiceName: serviceName2, Raw: marshaledCluster2}}, 129 }, 130 wantUpdateMD: xdsresource.UpdateMetadata{ 131 Status: xdsresource.ServiceStatusACKed, 132 }, 133 wantUpdateErr: false, 134 }, 135 // Response contains one cluster and it is good. 136 { 137 name: "one-good-cluster", 138 cdsResponse: goodCDSResponse1, 139 wantErr: false, 140 wantUpdate: map[string]xdsresource.ClusterUpdateErrTuple{ 141 goodClusterName1: {Update: xdsresource.ClusterUpdate{ClusterName: goodClusterName1, EDSServiceName: serviceName1, EnableLRS: true, Raw: marshaledCluster1}}, 142 }, 143 wantUpdateMD: xdsresource.UpdateMetadata{ 144 Status: xdsresource.ServiceStatusACKed, 145 }, 146 wantUpdateErr: false, 147 }, 148 } 149 for _, test := range tests { 150 t.Run(test.name, func(t *testing.T) { 151 testWatchHandle(t, &watchHandleTestcase{ 152 rType: xdsresource.ClusterResource, 153 resourceName: goodClusterName1, 154 155 responseToHandle: test.cdsResponse, 156 wantHandleErr: test.wantErr, 157 wantUpdate: test.wantUpdate, 158 wantUpdateMD: test.wantUpdateMD, 159 wantUpdateErr: test.wantUpdateErr, 160 }) 161 }) 162 } 163 } 164 165 // TestCDSHandleResponseWithoutWatch tests the case where the v2Client receives 166 // a CDS response without a registered watcher. 167 func (s) TestCDSHandleResponseWithoutWatch(t *testing.T) { 168 fakeServer, cleanup := startServer(t) 169 defer cleanup() 170 171 v2c, err := newTestController(&testUpdateReceiver{ 172 f: func(xdsresource.ResourceType, map[string]interface{}, xdsresource.UpdateMetadata) {}, 173 }, fakeServer.Address, goodNodeProto, func(int) time.Duration { return 0 }, nil) 174 if err != nil { 175 t.Fatal(err) 176 } 177 defer v2c.Close() 178 179 if _, _, _, err := v2c.handleResponse(badResourceTypeInLDSResponse); err == nil { 180 t.Fatal("v2c.handleCDSResponse() succeeded, should have failed") 181 } 182 183 if _, _, _, err := v2c.handleResponse(goodCDSResponse1); err != nil { 184 t.Fatal("v2c.handleCDSResponse() succeeded, should have failed") 185 } 186 }