@@ -26,11 +26,13 @@ import (
2626 "time"
2727
2828 "google.golang.org/grpc"
29+ "google.golang.org/grpc/balancer"
2930 "google.golang.org/grpc/codes"
3031 "google.golang.org/grpc/credentials/insecure"
3132 "google.golang.org/grpc/internal/grpcsync"
3233 "google.golang.org/grpc/internal/stubserver"
3334 rlstest "google.golang.org/grpc/internal/testutils/rls"
35+ "google.golang.org/grpc/internal/testutils/stats"
3436 "google.golang.org/grpc/metadata"
3537 "google.golang.org/grpc/status"
3638 "google.golang.org/protobuf/types/known/durationpb"
@@ -246,6 +248,133 @@ func (s) TestPick_DataCacheMiss_PendingEntryExists(t *testing.T) {
246248 }
247249}
248250
251+ // Test_RLSDefaultTargetPicksMetric tests the default target picks metric. It
252+ // configures an RLS Balancer which specifies to route to the default target in
253+ // the RLS Configuration, and makes an RPC on a Channel containing this RLS
254+ // Balancer. This test then asserts a default target picks metric is emitted,
255+ // and target pick or failed pick metric is not emitted.
256+ func (s ) Test_RLSDefaultTargetPicksMetric (t * testing.T ) {
257+ // Start an RLS server and set the throttler to always throttle requests.
258+ rlsServer , _ := rlstest .SetupFakeRLSServer (t , nil )
259+ overrideAdaptiveThrottler (t , alwaysThrottlingThrottler ())
260+
261+ // Build RLS service config with a default target.
262+ rlsConfig := buildBasicRLSConfigWithChildPolicy (t , t .Name (), rlsServer .Address )
263+ defBackendCh , defBackendAddress := startBackend (t )
264+ rlsConfig .RouteLookupConfig .DefaultTarget = defBackendAddress
265+
266+ // Register a manual resolver and push the RLS service config through it.
267+ r := startManualResolverWithConfig (t , rlsConfig )
268+
269+ tmr := stats .NewTestMetricsRecorder ()
270+ cc , err := grpc .Dial (r .Scheme ()+ ":///" , grpc .WithResolvers (r ), grpc .WithTransportCredentials (insecure .NewCredentials ()), grpc .WithStatsHandler (tmr ))
271+ if err != nil {
272+ t .Fatalf ("grpc.Dial() failed: %v" , err )
273+ }
274+ defer cc .Close ()
275+
276+ // Make an RPC and ensure it gets routed to the default target.
277+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
278+ defer cancel ()
279+ makeTestRPCAndExpectItToReachBackend (ctx , t , cc , defBackendCh )
280+
281+ if got , _ := tmr .Metric ("grpc.lb.rls.default_target_picks" ); got != 1 {
282+ t .Fatalf ("Unexpected data for metric %v, got: %v, want: %v" , "grpc.lb.rls.default_target_picks" , got , 1 )
283+ }
284+ if _ , ok := tmr .Metric ("grpc.lb.rls.target_picks" ); ok {
285+ t .Fatalf ("Data is present for metric %v" , "grpc.lb.rls.target_picks" )
286+ }
287+ if _ , ok := tmr .Metric ("grpc.lb.rls.failed_picks" ); ok {
288+ t .Fatalf ("Data is present for metric %v" , "grpc.lb.rls.failed_picks" )
289+ }
290+ }
291+
292+ // Test_RLSTargetPicksMetric tests the target picks metric. It configures an RLS
293+ // Balancer which specifies to route to a target through a RouteLookupResponse,
294+ // and makes an RPC on a Channel containing this RLS Balancer. This test then
295+ // asserts a target picks metric is emitted, and default target pick or failed
296+ // pick metric is not emitted.
297+ func (s ) Test_RLSTargetPicksMetric (t * testing.T ) {
298+ // Start an RLS server and set the throttler to never throttle requests.
299+ rlsServer , _ := rlstest .SetupFakeRLSServer (t , nil )
300+ overrideAdaptiveThrottler (t , neverThrottlingThrottler ())
301+
302+ // Build the RLS config without a default target.
303+ rlsConfig := buildBasicRLSConfigWithChildPolicy (t , t .Name (), rlsServer .Address )
304+
305+ // Start a test backend, and setup the fake RLS server to return this as a
306+ // target in the RLS response.
307+ testBackendCh , testBackendAddress := startBackend (t )
308+ rlsServer .SetResponseCallback (func (context.Context , * rlspb.RouteLookupRequest ) * rlstest.RouteLookupResponse {
309+ return & rlstest.RouteLookupResponse {Resp : & rlspb.RouteLookupResponse {Targets : []string {testBackendAddress }}}
310+ })
311+
312+ // Register a manual resolver and push the RLS service config through it.
313+ r := startManualResolverWithConfig (t , rlsConfig )
314+
315+ tmr := stats .NewTestMetricsRecorder ()
316+ // Dial the backend.
317+ cc , err := grpc .Dial (r .Scheme ()+ ":///" , grpc .WithResolvers (r ), grpc .WithTransportCredentials (insecure .NewCredentials ()), grpc .WithStatsHandler (tmr ))
318+ if err != nil {
319+ t .Fatalf ("grpc.Dial() failed: %v" , err )
320+ }
321+ defer cc .Close ()
322+
323+ // Make an RPC and ensure it gets routed to the test backend.
324+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
325+ defer cancel ()
326+ makeTestRPCAndExpectItToReachBackend (ctx , t , cc , testBackendCh )
327+ if got , _ := tmr .Metric ("grpc.lb.rls.target_picks" ); got != 1 {
328+ t .Fatalf ("Unexpected data for metric %v, got: %v, want: %v" , "grpc.lb.rls.target_picks" , got , 1 )
329+ }
330+ if _ , ok := tmr .Metric ("grpc.lb.rls.default_target_picks" ); ok {
331+ t .Fatalf ("Data is present for metric %v" , "grpc.lb.rls.default_target_picks" )
332+ }
333+ if _ , ok := tmr .Metric ("grpc.lb.rls.failed_picks" ); ok {
334+ t .Fatalf ("Data is present for metric %v" , "grpc.lb.rls.failed_picks" )
335+ }
336+ }
337+
338+ // Test_RLSFailedPicksMetric tests the failed picks metric. It configures an RLS
339+ // Balancer to fail a pick with unavailable, and makes an RPC on a Channel
340+ // containing this RLS Balancer. This test then asserts a failed picks metric is
341+ // emitted, and default target pick or target pick metric is not emitted.
342+ func (s ) Test_RLSFailedPicksMetric (t * testing.T ) {
343+ // Start an RLS server and set the throttler to never throttle requests.
344+ rlsServer , _ := rlstest .SetupFakeRLSServer (t , nil )
345+ overrideAdaptiveThrottler (t , neverThrottlingThrottler ())
346+
347+ // Build an RLS config without a default target.
348+ rlsConfig := buildBasicRLSConfigWithChildPolicy (t , t .Name (), rlsServer .Address )
349+
350+ // Register a manual resolver and push the RLS service config through it.
351+ r := startManualResolverWithConfig (t , rlsConfig )
352+
353+ tmr := stats .NewTestMetricsRecorder ()
354+ // Dial the backend.
355+ cc , err := grpc .Dial (r .Scheme ()+ ":///" , grpc .WithResolvers (r ), grpc .WithTransportCredentials (insecure .NewCredentials ()), grpc .WithStatsHandler (tmr ))
356+ if err != nil {
357+ t .Fatalf ("grpc.Dial() failed: %v" , err )
358+ }
359+ defer cc .Close ()
360+
361+ // Make an RPC and expect it to fail with deadline exceeded error. We use a
362+ // smaller timeout to ensure that the test doesn't run very long.
363+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestShortTimeout )
364+ defer cancel ()
365+ makeTestRPCAndVerifyError (ctx , t , cc , codes .Unavailable , errors .New ("RLS response's target list does not contain any entries for key" ))
366+
367+ if got , _ := tmr .Metric ("grpc.lb.rls.failed_picks" ); got != 1 {
368+ t .Fatalf ("Unexpected data for metric %v, got: %v, want: %v" , "grpc.lb.rls.failed_picks" , got , 1 )
369+ }
370+ if _ , ok := tmr .Metric ("grpc.lb.rls.target_picks" ); ok {
371+ t .Fatalf ("Data is present for metric %v" , "grpc.lb.rls.target_picks" )
372+ }
373+ if _ , ok := tmr .Metric ("grpc.lb.rls.default_target_picks" ); ok {
374+ t .Fatalf ("Data is present for metric %v" , "grpc.lb.rls.default_target_picks" )
375+ }
376+ }
377+
249378// Test verifies the scenario where there is a matching entry in the data cache
250379// which is valid and there is no pending request. The pick is expected to be
251380// delegated to the child policy.
@@ -256,7 +385,6 @@ func (s) TestPick_DataCacheHit_NoPendingEntry_ValidEntry(t *testing.T) {
256385
257386 // Build the RLS config without a default target.
258387 rlsConfig := buildBasicRLSConfigWithChildPolicy (t , t .Name (), rlsServer .Address )
259-
260388 // Start a test backend, and setup the fake RLS server to return this as a
261389 // target in the RLS response.
262390 testBackendCh , testBackendAddress := startBackend (t )
@@ -881,3 +1009,41 @@ func TestIsFullMethodNameValid(t *testing.T) {
8811009 })
8821010 }
8831011}
1012+
1013+ // Tests the conversion of the child pickers error to the pick result attribute.
1014+ func (s ) TestChildPickResultError (t * testing.T ) {
1015+ tests := []struct {
1016+ name string
1017+ err error
1018+ want string
1019+ }{
1020+ {
1021+ name : "nil" ,
1022+ err : nil ,
1023+ want : "complete" ,
1024+ },
1025+ {
1026+ name : "errNoSubConnAvailable" ,
1027+ err : balancer .ErrNoSubConnAvailable ,
1028+ want : "queue" ,
1029+ },
1030+ {
1031+ name : "status error" ,
1032+ err : status .Error (codes .Unimplemented , "unimplemented" ),
1033+ want : "drop" ,
1034+ },
1035+ {
1036+ name : "other error" ,
1037+ err : errors .New ("some error" ),
1038+ want : "fail" ,
1039+ },
1040+ }
1041+
1042+ for _ , test := range tests {
1043+ t .Run (test .name , func (t * testing.T ) {
1044+ if got := errToPickResult (test .err ); got != test .want {
1045+ t .Fatalf ("errToPickResult(%q) = %v, want %v" , test .err , got , test .want )
1046+ }
1047+ })
1048+ }
1049+ }
0 commit comments