github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/balancer/rls/internal/helpers_test.go (about) 1 /* 2 * 3 * Copyright 2021 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 rls 20 21 import ( 22 "context" 23 "net" 24 "strings" 25 "sync" 26 "testing" 27 "time" 28 29 grpc "github.com/hxx258456/ccgo/grpc" 30 "github.com/hxx258456/ccgo/grpc/balancer/rls/internal/test/e2e" 31 "github.com/hxx258456/ccgo/grpc/codes" 32 "github.com/hxx258456/ccgo/grpc/internal" 33 "github.com/hxx258456/ccgo/grpc/internal/balancergroup" 34 "github.com/hxx258456/ccgo/grpc/internal/grpctest" 35 rlspb "github.com/hxx258456/ccgo/grpc/internal/proto/grpc_lookup_v1" 36 internalserviceconfig "github.com/hxx258456/ccgo/grpc/internal/serviceconfig" 37 "github.com/hxx258456/ccgo/grpc/internal/stubserver" 38 "github.com/hxx258456/ccgo/grpc/internal/testutils" 39 "github.com/hxx258456/ccgo/grpc/resolver" 40 "github.com/hxx258456/ccgo/grpc/resolver/manual" 41 "github.com/hxx258456/ccgo/grpc/serviceconfig" 42 "github.com/hxx258456/ccgo/grpc/status" 43 testgrpc "github.com/hxx258456/ccgo/grpc/test/grpc_testing" 44 testpb "github.com/hxx258456/ccgo/grpc/test/grpc_testing" 45 "google.golang.org/protobuf/types/known/durationpb" 46 ) 47 48 // TODO(easwars): Remove this once all RLS code is merged. 49 //lint:file-ignore U1000 Ignore all unused code, not all code is merged yet. 50 51 const ( 52 defaultTestTimeout = 5 * time.Second 53 defaultTestShortTimeout = 100 * time.Millisecond 54 ) 55 56 func init() { 57 balancergroup.DefaultSubBalancerCloseTimeout = time.Millisecond 58 } 59 60 type s struct { 61 grpctest.Tester 62 } 63 64 func Test(t *testing.T) { 65 grpctest.RunSubTests(t, s{}) 66 } 67 68 // connWrapper wraps a net.Conn and pushes on a channel when closed. 69 type connWrapper struct { 70 net.Conn 71 closeCh *testutils.Channel 72 } 73 74 func (cw *connWrapper) Close() error { 75 err := cw.Conn.Close() 76 cw.closeCh.Replace(nil) 77 return err 78 } 79 80 // listenerWrapper wraps a net.Listener and the returned net.Conn. 81 // 82 // It pushes on a channel whenever it accepts a new connection. 83 type listenerWrapper struct { 84 net.Listener 85 newConnCh *testutils.Channel 86 } 87 88 func (l *listenerWrapper) Accept() (net.Conn, error) { 89 c, err := l.Listener.Accept() 90 if err != nil { 91 return nil, err 92 } 93 closeCh := testutils.NewChannel() 94 conn := &connWrapper{Conn: c, closeCh: closeCh} 95 l.newConnCh.Send(conn) 96 return conn, nil 97 } 98 99 func newListenerWrapper(t *testing.T, lis net.Listener) *listenerWrapper { 100 if lis == nil { 101 var err error 102 lis, err = testutils.LocalTCPListener() 103 if err != nil { 104 t.Fatal(err) 105 } 106 } 107 108 return &listenerWrapper{ 109 Listener: lis, 110 newConnCh: testutils.NewChannel(), 111 } 112 } 113 114 // fakeBackoffStrategy is a fake implementation of the backoff.Strategy 115 // interface, for tests to inject the backoff duration. 116 type fakeBackoffStrategy struct { 117 backoff time.Duration 118 } 119 120 func (f *fakeBackoffStrategy) Backoff(retries int) time.Duration { 121 return f.backoff 122 } 123 124 // fakeThrottler is a fake implementation of the adaptiveThrottler interface. 125 type fakeThrottler struct { 126 throttleFunc func() bool 127 } 128 129 func (f *fakeThrottler) ShouldThrottle() bool { return f.throttleFunc() } 130 func (f *fakeThrottler) RegisterBackendResponse(bool) {} 131 132 // alwaysThrottlingThrottler returns a fake throttler which always throttles. 133 func alwaysThrottlingThrottler() *fakeThrottler { 134 return &fakeThrottler{throttleFunc: func() bool { return true }} 135 } 136 137 // neverThrottlingThrottler returns a fake throttler which never throttles. 138 func neverThrottlingThrottler() *fakeThrottler { 139 return &fakeThrottler{throttleFunc: func() bool { return false }} 140 } 141 142 // oneTimeAllowingThrottler returns a fake throttler which does not throttle the 143 // first request, but throttles everything that comes after. This is useful for 144 // tests which need to set up a valid cache entry before testing other cases. 145 func oneTimeAllowingThrottler() *fakeThrottler { 146 var once sync.Once 147 return &fakeThrottler{ 148 throttleFunc: func() bool { 149 throttle := true 150 once.Do(func() { throttle = false }) 151 return throttle 152 }, 153 } 154 } 155 156 func overrideAdaptiveThrottler(t *testing.T, f *fakeThrottler) { 157 origAdaptiveThrottler := newAdaptiveThrottler 158 newAdaptiveThrottler = func() adaptiveThrottler { return f } 159 t.Cleanup(func() { newAdaptiveThrottler = origAdaptiveThrottler }) 160 } 161 162 // setupFakeRLSServer starts and returns a fake RouteLookupService server 163 // listening on the given listener or on a random local port. Also returns a 164 // channel for tests to get notified whenever the RouteLookup RPC is invoked on 165 // the fake server. 166 // 167 // This function sets up the fake server to respond with an empty response for 168 // the RouteLookup RPCs. Tests can override this by calling the 169 // SetResponseCallback() method on the returned fake server. 170 func setupFakeRLSServer(t *testing.T, lis net.Listener, opts ...grpc.ServerOption) (*e2e.FakeRouteLookupServer, chan struct{}) { 171 s, cancel := e2e.StartFakeRouteLookupServer(t, lis, opts...) 172 t.Logf("Started fake RLS server at %q", s.Address) 173 174 ch := make(chan struct{}, 1) 175 s.SetRequestCallback(func(request *rlspb.RouteLookupRequest) { 176 select { 177 case ch <- struct{}{}: 178 default: 179 } 180 }) 181 t.Cleanup(cancel) 182 return s, ch 183 } 184 185 // buildBasicRLSConfig constructs a basic service config for the RLS LB policy 186 // which header matching rules. This expects the passed child policy name to 187 // have been registered by the caller. 188 func buildBasicRLSConfig(childPolicyName, rlsServerAddress string) *e2e.RLSConfig { 189 return &e2e.RLSConfig{ 190 RouteLookupConfig: &rlspb.RouteLookupConfig{ 191 GrpcKeybuilders: []*rlspb.GrpcKeyBuilder{ 192 { 193 Names: []*rlspb.GrpcKeyBuilder_Name{{Service: "grpc.testing.TestService"}}, 194 Headers: []*rlspb.NameMatcher{ 195 {Key: "k1", Names: []string{"n1"}}, 196 {Key: "k2", Names: []string{"n2"}}, 197 }, 198 }, 199 }, 200 LookupService: rlsServerAddress, 201 LookupServiceTimeout: durationpb.New(defaultTestTimeout), 202 CacheSizeBytes: 1024, 203 }, 204 ChildPolicy: &internalserviceconfig.BalancerConfig{Name: childPolicyName}, 205 ChildPolicyConfigTargetFieldName: e2e.RLSChildPolicyTargetNameField, 206 } 207 } 208 209 // buildBasicRLSConfigWithChildPolicy constructs a very basic service config for 210 // the RLS LB policy. It also registers a test LB policy which is capable of 211 // being a child of the RLS LB policy. 212 func buildBasicRLSConfigWithChildPolicy(t *testing.T, childPolicyName, rlsServerAddress string) *e2e.RLSConfig { 213 childPolicyName = "test-child-policy" + childPolicyName 214 e2e.RegisterRLSChildPolicy(childPolicyName, nil) 215 t.Logf("Registered child policy with name %q", childPolicyName) 216 217 return &e2e.RLSConfig{ 218 RouteLookupConfig: &rlspb.RouteLookupConfig{ 219 GrpcKeybuilders: []*rlspb.GrpcKeyBuilder{{Names: []*rlspb.GrpcKeyBuilder_Name{{Service: "grpc.testing.TestService"}}}}, 220 LookupService: rlsServerAddress, 221 LookupServiceTimeout: durationpb.New(defaultTestTimeout), 222 CacheSizeBytes: 1024, 223 }, 224 ChildPolicy: &internalserviceconfig.BalancerConfig{Name: childPolicyName}, 225 ChildPolicyConfigTargetFieldName: e2e.RLSChildPolicyTargetNameField, 226 } 227 } 228 229 // startBackend starts a backend implementing the TestService on a local port. 230 // It returns a channel for tests to get notified whenever an RPC is invoked on 231 // the backend. This allows tests to ensure that RPCs reach expected backends. 232 // Also returns the address of the backend. 233 func startBackend(t *testing.T, sopts ...grpc.ServerOption) (rpcCh chan struct{}, address string) { 234 t.Helper() 235 236 rpcCh = make(chan struct{}, 1) 237 backend := &stubserver.StubServer{ 238 EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { 239 select { 240 case rpcCh <- struct{}{}: 241 default: 242 } 243 return &testpb.Empty{}, nil 244 }, 245 } 246 if err := backend.StartServer(sopts...); err != nil { 247 t.Fatalf("Failed to start backend: %v", err) 248 } 249 t.Logf("Started TestService backend at: %q", backend.Address) 250 t.Cleanup(func() { backend.Stop() }) 251 return rpcCh, backend.Address 252 } 253 254 // startManualResolverWithConfig registers and returns a manual resolver which 255 // pushes the RLS LB policy's service config on the channel. 256 func startManualResolverWithConfig(t *testing.T, rlsConfig *e2e.RLSConfig) *manual.Resolver { 257 t.Helper() 258 259 scJSON, err := rlsConfig.ServiceConfigJSON() 260 if err != nil { 261 t.Fatal(err) 262 } 263 264 sc := internal.ParseServiceConfigForTesting.(func(string) *serviceconfig.ParseResult)(scJSON) 265 r := manual.NewBuilderWithScheme("rls-e2e") 266 r.InitialState(resolver.State{ServiceConfig: sc}) 267 t.Cleanup(r.Close) 268 return r 269 } 270 271 // makeTestRPCAndExpectItToReachBackend is a test helper function which makes 272 // the EmptyCall RPC on the given ClientConn and verifies that it reaches a 273 // backend. The latter is accomplished by listening on the provided channel 274 // which gets pushed to whenever the backend in question gets an RPC. 275 func makeTestRPCAndExpectItToReachBackend(ctx context.Context, t *testing.T, cc *grpc.ClientConn, ch chan struct{}) { 276 t.Helper() 277 278 client := testgrpc.NewTestServiceClient(cc) 279 if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil { 280 t.Fatalf("TestService/EmptyCall() failed with error: %v", err) 281 } 282 select { 283 case <-ctx.Done(): 284 t.Fatalf("Timeout when waiting for backend to receive RPC") 285 case <-ch: 286 } 287 } 288 289 // makeTestRPCAndVerifyError is a test helper function which makes the EmptyCall 290 // RPC on the given ClientConn and verifies that the RPC fails with the given 291 // status code and error. 292 func makeTestRPCAndVerifyError(ctx context.Context, t *testing.T, cc *grpc.ClientConn, wantCode codes.Code, wantErr error) { 293 t.Helper() 294 295 client := testgrpc.NewTestServiceClient(cc) 296 _, err := client.EmptyCall(ctx, &testpb.Empty{}) 297 if err == nil { 298 t.Fatal("TestService/EmptyCall() succeeded when expected to fail") 299 } 300 if code := status.Code(err); code != wantCode { 301 t.Fatalf("TestService/EmptyCall() returned code: %v, want: %v", code, wantCode) 302 } 303 if wantErr != nil && !strings.Contains(err.Error(), wantErr.Error()) { 304 t.Fatalf("TestService/EmptyCall() returned err: %v, want: %v", err, wantErr) 305 } 306 } 307 308 // verifyRLSRequest is a test helper which listens on a channel to see if an RLS 309 // request was received by the fake RLS server. Based on whether the test 310 // expects a request to be sent out or not, it uses a different timeout. 311 func verifyRLSRequest(t *testing.T, ch chan struct{}, wantRequest bool) { 312 t.Helper() 313 314 if wantRequest { 315 select { 316 case <-time.After(defaultTestTimeout): 317 t.Fatalf("Timeout when waiting for an RLS request to be sent out") 318 case <-ch: 319 } 320 } else { 321 select { 322 case <-time.After(defaultTestShortTimeout): 323 case <-ch: 324 t.Fatalf("RLS request sent out when not expecting one") 325 } 326 } 327 }