gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/xds/internal/xdsclient/controller/v2_rds_test.go (about) 1 /* 2 * 3 * Copyright 2020 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 "context" 23 "testing" 24 "time" 25 26 xdspb "gitee.com/ks-custle/core-gm/go-control-plane/envoy/api/v2" 27 "gitee.com/ks-custle/core-gm/grpc/xds/internal/testutils/fakeserver" 28 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource" 29 "github.com/google/go-cmp/cmp/cmpopts" 30 ) 31 32 // doLDS makes a LDS watch, and waits for the response and ack to finish. 33 // 34 // This is called by RDS tests to start LDS first, because LDS is a 35 // pre-requirement for RDS, and RDS handle would fail without an existing LDS 36 // watch. 37 func doLDS(ctx context.Context, t *testing.T, v2c *Controller, fakeServer *fakeserver.Server) { 38 v2c.AddWatch(xdsresource.ListenerResource, goodLDSTarget1) 39 if _, err := fakeServer.XDSRequestChan.Receive(ctx); err != nil { 40 t.Fatalf("Timeout waiting for LDS request: %v", err) 41 } 42 } 43 44 // TestRDSHandleResponseWithRouting starts a fake xDS server, makes a ClientConn 45 // to it, and creates a v2Client using it. Then, it registers an LDS and RDS 46 // watcher and tests different RDS responses. 47 func (s) TestRDSHandleResponseWithRouting(t *testing.T) { 48 tests := []struct { 49 name string 50 rdsResponse *xdspb.DiscoveryResponse 51 wantErr bool 52 wantUpdate map[string]xdsresource.RouteConfigUpdateErrTuple 53 wantUpdateMD xdsresource.UpdateMetadata 54 wantUpdateErr bool 55 }{ 56 // Badly marshaled RDS response. 57 { 58 name: "badly-marshaled-response", 59 rdsResponse: badlyMarshaledRDSResponse, 60 wantErr: true, 61 wantUpdate: nil, 62 wantUpdateMD: xdsresource.UpdateMetadata{ 63 Status: xdsresource.ServiceStatusNACKed, 64 ErrState: &xdsresource.UpdateErrorMetadata{ 65 Err: cmpopts.AnyError, 66 }, 67 }, 68 wantUpdateErr: false, 69 }, 70 // Response does not contain RouteConfiguration proto. 71 { 72 name: "no-route-config-in-response", 73 rdsResponse: badResourceTypeInRDSResponse, 74 wantErr: true, 75 wantUpdate: nil, 76 wantUpdateMD: xdsresource.UpdateMetadata{ 77 Status: xdsresource.ServiceStatusNACKed, 78 ErrState: &xdsresource.UpdateErrorMetadata{ 79 Err: cmpopts.AnyError, 80 }, 81 }, 82 wantUpdateErr: false, 83 }, 84 // No virtualHosts in the response. Just one test case here for a bad 85 // RouteConfiguration, since the others are covered in 86 // TestGetClusterFromRouteConfiguration. 87 { 88 name: "no-virtual-hosts-in-response", 89 rdsResponse: noVirtualHostsInRDSResponse, 90 wantErr: false, 91 wantUpdate: map[string]xdsresource.RouteConfigUpdateErrTuple{ 92 goodRouteName1: {Update: xdsresource.RouteConfigUpdate{ 93 VirtualHosts: nil, 94 Raw: marshaledNoVirtualHostsRouteConfig, 95 }}, 96 }, 97 wantUpdateMD: xdsresource.UpdateMetadata{ 98 Status: xdsresource.ServiceStatusACKed, 99 }, 100 wantUpdateErr: false, 101 }, 102 // Response contains one good RouteConfiguration, uninteresting though. 103 { 104 name: "one-uninteresting-route-config", 105 rdsResponse: goodRDSResponse2, 106 wantErr: false, 107 wantUpdate: map[string]xdsresource.RouteConfigUpdateErrTuple{ 108 goodRouteName2: {Update: xdsresource.RouteConfigUpdate{ 109 VirtualHosts: []*xdsresource.VirtualHost{ 110 { 111 Domains: []string{uninterestingDomain}, 112 Routes: []*xdsresource.Route{{Prefix: newStringP(""), 113 WeightedClusters: map[string]xdsresource.WeightedCluster{uninterestingClusterName: {Weight: 1}}, 114 ActionType: xdsresource.RouteActionRoute}}, 115 }, 116 { 117 Domains: []string{goodLDSTarget1}, 118 Routes: []*xdsresource.Route{{ 119 Prefix: newStringP(""), 120 WeightedClusters: map[string]xdsresource.WeightedCluster{goodClusterName2: {Weight: 1}}, 121 ActionType: xdsresource.RouteActionRoute}}, 122 }, 123 }, 124 Raw: marshaledGoodRouteConfig2, 125 }}, 126 }, 127 wantUpdateMD: xdsresource.UpdateMetadata{ 128 Status: xdsresource.ServiceStatusACKed, 129 }, 130 wantUpdateErr: false, 131 }, 132 // Response contains one good interesting RouteConfiguration. 133 { 134 name: "one-good-route-config", 135 rdsResponse: goodRDSResponse1, 136 wantErr: false, 137 wantUpdate: map[string]xdsresource.RouteConfigUpdateErrTuple{ 138 goodRouteName1: {Update: xdsresource.RouteConfigUpdate{ 139 VirtualHosts: []*xdsresource.VirtualHost{ 140 { 141 Domains: []string{uninterestingDomain}, 142 Routes: []*xdsresource.Route{{ 143 Prefix: newStringP(""), 144 WeightedClusters: map[string]xdsresource.WeightedCluster{uninterestingClusterName: {Weight: 1}}, 145 ActionType: xdsresource.RouteActionRoute}}, 146 }, 147 { 148 Domains: []string{goodLDSTarget1}, 149 Routes: []*xdsresource.Route{{Prefix: newStringP(""), 150 WeightedClusters: map[string]xdsresource.WeightedCluster{goodClusterName1: {Weight: 1}}, 151 ActionType: xdsresource.RouteActionRoute}}, 152 }, 153 }, 154 Raw: marshaledGoodRouteConfig1, 155 }}, 156 }, 157 wantUpdateMD: xdsresource.UpdateMetadata{ 158 Status: xdsresource.ServiceStatusACKed, 159 }, 160 wantUpdateErr: false, 161 }, 162 } 163 for _, test := range tests { 164 t.Run(test.name, func(t *testing.T) { 165 testWatchHandle(t, &watchHandleTestcase{ 166 rType: xdsresource.RouteConfigResource, 167 resourceName: goodRouteName1, 168 responseToHandle: test.rdsResponse, 169 wantHandleErr: test.wantErr, 170 wantUpdate: test.wantUpdate, 171 wantUpdateMD: test.wantUpdateMD, 172 wantUpdateErr: test.wantUpdateErr, 173 }) 174 }) 175 } 176 } 177 178 // TestRDSHandleResponseWithoutRDSWatch tests the case where the v2Client 179 // receives an RDS response without a registered RDS watcher. 180 func (s) TestRDSHandleResponseWithoutRDSWatch(t *testing.T) { 181 fakeServer, cleanup := startServer(t) 182 defer cleanup() 183 184 v2c, err := newTestController(&testUpdateReceiver{ 185 f: func(xdsresource.ResourceType, map[string]interface{}, xdsresource.UpdateMetadata) {}, 186 }, fakeServer.Address, goodNodeProto, func(int) time.Duration { return 0 }, nil) 187 if err != nil { 188 t.Fatal(err) 189 } 190 defer v2c.Close() 191 192 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 193 defer cancel() 194 doLDS(ctx, t, v2c, fakeServer) 195 196 if _, _, _, err := v2c.handleResponse(badResourceTypeInRDSResponse); err == nil { 197 t.Fatal("v2c.handleRDSResponse() succeeded, should have failed") 198 } 199 200 if _, _, _, err := v2c.handleResponse(goodRDSResponse1); err != nil { 201 t.Fatal("v2c.handleRDSResponse() succeeded, should have failed") 202 } 203 }