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  }