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 fakexds provides fake implementation of multiple types, for use in 20// xds tests. 21package fakexds 22 23import ( 24 "sync" 25 26 "google.golang.org/grpc/xds/internal/balancer/lrs" 27 xdsclient "google.golang.org/grpc/xds/internal/client" 28 "google.golang.org/grpc/xds/internal/testutils" 29) 30 31// Client is a fake implementation of an xds client. It exposes a bunch of 32// channels to signal the occurrence of various events. 33type Client struct { 34 name string 35 suWatchCh *testutils.Channel 36 edsWatchCh *testutils.Channel 37 suCancelCh *testutils.Channel 38 edsCancelCh *testutils.Channel 39 loadReportCh *testutils.Channel 40 closeCh *testutils.Channel 41 42 mu sync.Mutex 43 serviceCb func(xdsclient.ServiceUpdate, error) 44 edsCb func(*xdsclient.EDSUpdate, error) 45} 46 47// WatchService registers a LDS/RDS watch. 48func (xdsC *Client) WatchService(target string, callback func(xdsclient.ServiceUpdate, error)) func() { 49 xdsC.mu.Lock() 50 defer xdsC.mu.Unlock() 51 52 xdsC.serviceCb = callback 53 xdsC.suWatchCh.Send(target) 54 return func() { 55 xdsC.suCancelCh.Send(nil) 56 } 57} 58 59// WaitForWatchService waits for WatchService to be invoked on this client 60// within a reasonable timeout, and returns the serviceName being watched. 61func (xdsC *Client) WaitForWatchService() (string, error) { 62 val, err := xdsC.suWatchCh.Receive() 63 return val.(string), err 64} 65 66// InvokeWatchServiceCallback invokes the registered service watch callback. 67func (xdsC *Client) InvokeWatchServiceCallback(cluster string, err error) { 68 xdsC.mu.Lock() 69 defer xdsC.mu.Unlock() 70 71 xdsC.serviceCb(xdsclient.ServiceUpdate{Cluster: cluster}, err) 72} 73 74// WatchEDS registers an EDS watch for provided clusterName. 75func (xdsC *Client) WatchEDS(clusterName string, callback func(*xdsclient.EDSUpdate, error)) (cancel func()) { 76 xdsC.mu.Lock() 77 defer xdsC.mu.Unlock() 78 79 xdsC.edsCb = callback 80 xdsC.edsWatchCh.Send(clusterName) 81 return func() { 82 xdsC.edsCancelCh.Send(nil) 83 } 84} 85 86// WaitForWatchEDS waits for WatchEDS to be invoked on this client within a 87// reasonable timeout, and returns the clusterName being watched. 88func (xdsC *Client) WaitForWatchEDS() (string, error) { 89 val, err := xdsC.edsWatchCh.Receive() 90 return val.(string), err 91} 92 93// InvokeWatchEDSCallback invokes the registered edsWatch callback. 94func (xdsC *Client) InvokeWatchEDSCallback(update *xdsclient.EDSUpdate, err error) { 95 xdsC.mu.Lock() 96 defer xdsC.mu.Unlock() 97 98 xdsC.edsCb(update, err) 99} 100 101// ReportLoadArgs wraps the arguments passed to ReportLoad. 102type ReportLoadArgs struct { 103 // Server is the name of the server to which the load is reported. 104 Server string 105 // Cluster is the name of the cluster for which load is reported. 106 Cluster string 107} 108 109// ReportLoad starts reporting load about clusterName to server. 110func (xdsC *Client) ReportLoad(server string, clusterName string, loadStore lrs.Store) (cancel func()) { 111 xdsC.loadReportCh.Send(ReportLoadArgs{Server: server, Cluster: clusterName}) 112 return func() {} 113} 114 115// WaitForReportLoad waits for ReportLoad to be invoked on this client within a 116// reasonable timeout, and returns the arguments passed to it. 117func (xdsC *Client) WaitForReportLoad() (ReportLoadArgs, error) { 118 val, err := xdsC.loadReportCh.Receive() 119 return val.(ReportLoadArgs), err 120} 121 122// Close closes the xds client. 123func (xdsC *Client) Close() { 124 xdsC.closeCh.Send(nil) 125} 126 127// Name returns the name of the xds client. 128func (xdsC *Client) Name() string { 129 return xdsC.name 130} 131 132// NewClient returns a new fake xds client. 133func NewClient() *Client { 134 return NewClientWithName("") 135} 136 137// NewClientWithName returns a new fake xds client with the provided name. This 138// is used in cases where multiple clients are created in the tests and we need 139// to make sure the client is created for the expected balancer name. 140func NewClientWithName(name string) *Client { 141 return &Client{ 142 name: name, 143 suWatchCh: testutils.NewChannel(), 144 edsWatchCh: testutils.NewChannel(), 145 suCancelCh: testutils.NewChannel(), 146 edsCancelCh: testutils.NewChannel(), 147 loadReportCh: testutils.NewChannel(), 148 closeCh: testutils.NewChannel(), 149 } 150} 151