gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/xds/internal/testutils/fakeclient/client.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 fakeclient provides a fake implementation of an xDS client.
    20  package fakeclient
    21  
    22  import (
    23  	"context"
    24  
    25  	"gitee.com/ks-custle/core-gm/grpc/internal/grpcsync"
    26  	"gitee.com/ks-custle/core-gm/grpc/internal/testutils"
    27  	"gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient"
    28  	"gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/bootstrap"
    29  	"gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/load"
    30  	"gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource"
    31  )
    32  
    33  // Client is a fake implementation of an xds client. It exposes a bunch of
    34  // channels to signal the occurrence of various events.
    35  type Client struct {
    36  	// Embed XDSClient so this fake client implements the interface, but it's
    37  	// never set (it's always nil). This may cause nil panic since not all the
    38  	// methods are implemented.
    39  	xdsclient.XDSClient
    40  
    41  	name         string
    42  	ldsWatchCh   *testutils.Channel
    43  	rdsWatchCh   *testutils.Channel
    44  	cdsWatchCh   *testutils.Channel
    45  	edsWatchCh   *testutils.Channel
    46  	ldsCancelCh  *testutils.Channel
    47  	rdsCancelCh  *testutils.Channel
    48  	cdsCancelCh  *testutils.Channel
    49  	edsCancelCh  *testutils.Channel
    50  	loadReportCh *testutils.Channel
    51  	lrsCancelCh  *testutils.Channel
    52  	loadStore    *load.Store
    53  	bootstrapCfg *bootstrap.Config
    54  
    55  	ldsCb  func(xdsresource.ListenerUpdate, error)
    56  	rdsCbs map[string]func(xdsresource.RouteConfigUpdate, error)
    57  	cdsCbs map[string]func(xdsresource.ClusterUpdate, error)
    58  	edsCbs map[string]func(xdsresource.EndpointsUpdate, error)
    59  
    60  	Closed *grpcsync.Event // fired when Close is called.
    61  }
    62  
    63  // WatchListener registers a LDS watch.
    64  func (xdsC *Client) WatchListener(serviceName string, callback func(xdsresource.ListenerUpdate, error)) func() {
    65  	xdsC.ldsCb = callback
    66  	xdsC.ldsWatchCh.Send(serviceName)
    67  	return func() {
    68  		xdsC.ldsCancelCh.Send(nil)
    69  	}
    70  }
    71  
    72  // WaitForWatchListener waits for WatchCluster to be invoked on this client and
    73  // returns the serviceName being watched.
    74  func (xdsC *Client) WaitForWatchListener(ctx context.Context) (string, error) {
    75  	val, err := xdsC.ldsWatchCh.Receive(ctx)
    76  	if err != nil {
    77  		return "", err
    78  	}
    79  	return val.(string), err
    80  }
    81  
    82  // InvokeWatchListenerCallback invokes the registered ldsWatch callback.
    83  //
    84  // Not thread safe with WatchListener. Only call this after
    85  // WaitForWatchListener.
    86  func (xdsC *Client) InvokeWatchListenerCallback(update xdsresource.ListenerUpdate, err error) {
    87  	xdsC.ldsCb(update, err)
    88  }
    89  
    90  // WaitForCancelListenerWatch waits for a LDS watch to be cancelled  and returns
    91  // context.DeadlineExceeded otherwise.
    92  func (xdsC *Client) WaitForCancelListenerWatch(ctx context.Context) error {
    93  	_, err := xdsC.ldsCancelCh.Receive(ctx)
    94  	return err
    95  }
    96  
    97  // WatchRouteConfig registers a RDS watch.
    98  func (xdsC *Client) WatchRouteConfig(routeName string, callback func(xdsresource.RouteConfigUpdate, error)) func() {
    99  	xdsC.rdsCbs[routeName] = callback
   100  	xdsC.rdsWatchCh.Send(routeName)
   101  	return func() {
   102  		xdsC.rdsCancelCh.Send(routeName)
   103  	}
   104  }
   105  
   106  // WaitForWatchRouteConfig waits for WatchCluster to be invoked on this client and
   107  // returns the routeName being watched.
   108  func (xdsC *Client) WaitForWatchRouteConfig(ctx context.Context) (string, error) {
   109  	val, err := xdsC.rdsWatchCh.Receive(ctx)
   110  	if err != nil {
   111  		return "", err
   112  	}
   113  	return val.(string), err
   114  }
   115  
   116  // InvokeWatchRouteConfigCallback invokes the registered rdsWatch callback.
   117  //
   118  // Not thread safe with WatchRouteConfig. Only call this after
   119  // WaitForWatchRouteConfig.
   120  func (xdsC *Client) InvokeWatchRouteConfigCallback(name string, update xdsresource.RouteConfigUpdate, err error) {
   121  	if len(xdsC.rdsCbs) != 1 {
   122  		xdsC.rdsCbs[name](update, err)
   123  		return
   124  	}
   125  	// Keeps functionality with previous usage of this on client side, if single
   126  	// callback call that callback.
   127  	var routeName string
   128  	for route := range xdsC.rdsCbs {
   129  		routeName = route
   130  	}
   131  	xdsC.rdsCbs[routeName](update, err)
   132  }
   133  
   134  // WaitForCancelRouteConfigWatch waits for a RDS watch to be cancelled  and returns
   135  // context.DeadlineExceeded otherwise.
   136  func (xdsC *Client) WaitForCancelRouteConfigWatch(ctx context.Context) (string, error) {
   137  	val, err := xdsC.rdsCancelCh.Receive(ctx)
   138  	if err != nil {
   139  		return "", err
   140  	}
   141  	return val.(string), err
   142  }
   143  
   144  // WatchCluster registers a CDS watch.
   145  func (xdsC *Client) WatchCluster(clusterName string, callback func(xdsresource.ClusterUpdate, error)) func() {
   146  	// Due to the tree like structure of aggregate clusters, there can be multiple callbacks persisted for each cluster
   147  	// node. However, the client doesn't care about the parent child relationship between the nodes, only that it invokes
   148  	// the right callback for a particular cluster.
   149  	xdsC.cdsCbs[clusterName] = callback
   150  	xdsC.cdsWatchCh.Send(clusterName)
   151  	return func() {
   152  		xdsC.cdsCancelCh.Send(clusterName)
   153  	}
   154  }
   155  
   156  // WaitForWatchCluster waits for WatchCluster to be invoked on this client and
   157  // returns the clusterName being watched.
   158  func (xdsC *Client) WaitForWatchCluster(ctx context.Context) (string, error) {
   159  	val, err := xdsC.cdsWatchCh.Receive(ctx)
   160  	if err != nil {
   161  		return "", err
   162  	}
   163  	return val.(string), err
   164  }
   165  
   166  // InvokeWatchClusterCallback invokes the registered cdsWatch callback.
   167  //
   168  // Not thread safe with WatchCluster. Only call this after
   169  // WaitForWatchCluster.
   170  func (xdsC *Client) InvokeWatchClusterCallback(update xdsresource.ClusterUpdate, err error) {
   171  	// Keeps functionality with previous usage of this, if single callback call that callback.
   172  	if len(xdsC.cdsCbs) == 1 {
   173  		var clusterName string
   174  		for cluster := range xdsC.cdsCbs {
   175  			clusterName = cluster
   176  		}
   177  		xdsC.cdsCbs[clusterName](update, err)
   178  	} else {
   179  		// Have what callback you call with the update determined by the service name in the ClusterUpdate. Left up to the
   180  		// caller to make sure the cluster update matches with a persisted callback.
   181  		xdsC.cdsCbs[update.ClusterName](update, err)
   182  	}
   183  }
   184  
   185  // WaitForCancelClusterWatch waits for a CDS watch to be cancelled  and returns
   186  // context.DeadlineExceeded otherwise.
   187  func (xdsC *Client) WaitForCancelClusterWatch(ctx context.Context) (string, error) {
   188  	clusterNameReceived, err := xdsC.cdsCancelCh.Receive(ctx)
   189  	if err != nil {
   190  		return "", err
   191  	}
   192  	return clusterNameReceived.(string), err
   193  }
   194  
   195  // WatchEndpoints registers an EDS watch for provided clusterName.
   196  func (xdsC *Client) WatchEndpoints(clusterName string, callback func(xdsresource.EndpointsUpdate, error)) (cancel func()) {
   197  	xdsC.edsCbs[clusterName] = callback
   198  	xdsC.edsWatchCh.Send(clusterName)
   199  	return func() {
   200  		xdsC.edsCancelCh.Send(clusterName)
   201  	}
   202  }
   203  
   204  // WaitForWatchEDS waits for WatchEndpoints to be invoked on this client and
   205  // returns the clusterName being watched.
   206  func (xdsC *Client) WaitForWatchEDS(ctx context.Context) (string, error) {
   207  	val, err := xdsC.edsWatchCh.Receive(ctx)
   208  	if err != nil {
   209  		return "", err
   210  	}
   211  	return val.(string), err
   212  }
   213  
   214  // InvokeWatchEDSCallback invokes the registered edsWatch callback.
   215  //
   216  // Not thread safe with WatchEndpoints. Only call this after
   217  // WaitForWatchEDS.
   218  func (xdsC *Client) InvokeWatchEDSCallback(name string, update xdsresource.EndpointsUpdate, err error) {
   219  	if len(xdsC.edsCbs) != 1 {
   220  		// This may panic if name isn't found. But it's fine for tests.
   221  		xdsC.edsCbs[name](update, err)
   222  		return
   223  	}
   224  	// Keeps functionality with previous usage of this, if single callback call
   225  	// that callback.
   226  	for n := range xdsC.edsCbs {
   227  		name = n
   228  	}
   229  	xdsC.edsCbs[name](update, err)
   230  }
   231  
   232  // WaitForCancelEDSWatch waits for a EDS watch to be cancelled and returns
   233  // context.DeadlineExceeded otherwise.
   234  func (xdsC *Client) WaitForCancelEDSWatch(ctx context.Context) (string, error) {
   235  	edsNameReceived, err := xdsC.edsCancelCh.Receive(ctx)
   236  	if err != nil {
   237  		return "", err
   238  	}
   239  	return edsNameReceived.(string), err
   240  }
   241  
   242  // ReportLoadArgs wraps the arguments passed to ReportLoad.
   243  type ReportLoadArgs struct {
   244  	// Server is the name of the server to which the load is reported.
   245  	Server string
   246  }
   247  
   248  // ReportLoad starts reporting load about clusterName to server.
   249  func (xdsC *Client) ReportLoad(server string) (loadStore *load.Store, cancel func()) {
   250  	xdsC.loadReportCh.Send(ReportLoadArgs{Server: server})
   251  	return xdsC.loadStore, func() {
   252  		xdsC.lrsCancelCh.Send(nil)
   253  	}
   254  }
   255  
   256  // WaitForCancelReportLoad waits for a load report to be cancelled and returns
   257  // context.DeadlineExceeded otherwise.
   258  func (xdsC *Client) WaitForCancelReportLoad(ctx context.Context) error {
   259  	_, err := xdsC.lrsCancelCh.Receive(ctx)
   260  	return err
   261  }
   262  
   263  // LoadStore returns the underlying load data store.
   264  func (xdsC *Client) LoadStore() *load.Store {
   265  	return xdsC.loadStore
   266  }
   267  
   268  // WaitForReportLoad waits for ReportLoad to be invoked on this client and
   269  // returns the arguments passed to it.
   270  func (xdsC *Client) WaitForReportLoad(ctx context.Context) (ReportLoadArgs, error) {
   271  	val, err := xdsC.loadReportCh.Receive(ctx)
   272  	if err != nil {
   273  		return ReportLoadArgs{}, err
   274  	}
   275  	return val.(ReportLoadArgs), nil
   276  }
   277  
   278  // Close fires xdsC.Closed, indicating it was called.
   279  func (xdsC *Client) Close() {
   280  	xdsC.Closed.Fire()
   281  }
   282  
   283  // BootstrapConfig returns the bootstrap config.
   284  func (xdsC *Client) BootstrapConfig() *bootstrap.Config {
   285  	return xdsC.bootstrapCfg
   286  }
   287  
   288  // SetBootstrapConfig updates the bootstrap config.
   289  func (xdsC *Client) SetBootstrapConfig(cfg *bootstrap.Config) {
   290  	xdsC.bootstrapCfg = cfg
   291  }
   292  
   293  // Name returns the name of the xds client.
   294  func (xdsC *Client) Name() string {
   295  	return xdsC.name
   296  }
   297  
   298  // NewClient returns a new fake xds client.
   299  func NewClient() *Client {
   300  	return NewClientWithName("")
   301  }
   302  
   303  // NewClientWithName returns a new fake xds client with the provided name. This
   304  // is used in cases where multiple clients are created in the tests and we need
   305  // to make sure the client is created for the expected balancer name.
   306  func NewClientWithName(name string) *Client {
   307  	return &Client{
   308  		name:         name,
   309  		ldsWatchCh:   testutils.NewChannelWithSize(10),
   310  		rdsWatchCh:   testutils.NewChannelWithSize(10),
   311  		cdsWatchCh:   testutils.NewChannelWithSize(10),
   312  		edsWatchCh:   testutils.NewChannelWithSize(10),
   313  		ldsCancelCh:  testutils.NewChannelWithSize(10),
   314  		rdsCancelCh:  testutils.NewChannelWithSize(10),
   315  		cdsCancelCh:  testutils.NewChannelWithSize(10),
   316  		edsCancelCh:  testutils.NewChannelWithSize(10),
   317  		loadReportCh: testutils.NewChannel(),
   318  		lrsCancelCh:  testutils.NewChannel(),
   319  		loadStore:    load.NewStore(),
   320  		bootstrapCfg: &bootstrap.Config{ClientDefaultListenerResourceNameTemplate: "%s"},
   321  		rdsCbs:       make(map[string]func(xdsresource.RouteConfigUpdate, error)),
   322  		cdsCbs:       make(map[string]func(xdsresource.ClusterUpdate, error)),
   323  		edsCbs:       make(map[string]func(xdsresource.EndpointsUpdate, error)),
   324  		Closed:       grpcsync.NewEvent(),
   325  	}
   326  }