google.golang.org/grpc@v1.62.1/test/xds/xds_client_retry_test.go (about) 1 /* 2 * 3 * Copyright 2022 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 xds_test 20 21 import ( 22 "context" 23 "fmt" 24 "testing" 25 26 "google.golang.org/grpc" 27 "google.golang.org/grpc/codes" 28 "google.golang.org/grpc/credentials/insecure" 29 "google.golang.org/grpc/internal/stubserver" 30 "google.golang.org/grpc/internal/testutils" 31 "google.golang.org/grpc/internal/testutils/xds/e2e" 32 "google.golang.org/grpc/status" 33 "google.golang.org/protobuf/types/known/wrapperspb" 34 35 v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" 36 testgrpc "google.golang.org/grpc/interop/grpc_testing" 37 testpb "google.golang.org/grpc/interop/grpc_testing" 38 ) 39 40 func (s) TestClientSideRetry(t *testing.T) { 41 ctr := 0 42 errs := []codes.Code{codes.ResourceExhausted} 43 44 managementServer, nodeID, _, resolver, cleanup1 := e2e.SetupManagementServer(t, e2e.ManagementServerOptions{}) 45 defer cleanup1() 46 47 server := stubserver.StartTestService(t, &stubserver.StubServer{ 48 EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { 49 defer func() { ctr++ }() 50 if ctr < len(errs) { 51 return nil, status.Errorf(errs[ctr], "this should be retried") 52 } 53 return &testpb.Empty{}, nil 54 }, 55 }) 56 defer server.Stop() 57 58 const serviceName = "my-service-client-side-xds" 59 resources := e2e.DefaultClientResources(e2e.ResourceParams{ 60 DialTarget: serviceName, 61 NodeID: nodeID, 62 Host: "localhost", 63 Port: testutils.ParsePort(t, server.Address), 64 SecLevel: e2e.SecurityLevelNone, 65 }) 66 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 67 if err := managementServer.Update(ctx, resources); err != nil { 68 t.Fatal(err) 69 } 70 71 // Create a ClientConn and make a successful RPC. 72 cc, err := grpc.Dial(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolver)) 73 if err != nil { 74 t.Fatalf("failed to dial local test server: %v", err) 75 } 76 defer cc.Close() 77 78 client := testgrpc.NewTestServiceClient(cc) 79 defer cancel() 80 if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); status.Code(err) != codes.ResourceExhausted { 81 t.Fatalf("rpc EmptyCall() = _, %v; want _, ResourceExhausted", err) 82 } 83 84 testCases := []struct { 85 name string 86 vhPolicy *v3routepb.RetryPolicy 87 routePolicy *v3routepb.RetryPolicy 88 errs []codes.Code // the errors returned by the server for each RPC 89 tryAgainErr codes.Code // the error that would be returned if we are still using the old retry policies. 90 errWant codes.Code 91 }{{ 92 name: "virtualHost only, fail", 93 vhPolicy: &v3routepb.RetryPolicy{ 94 RetryOn: "resource-exhausted,unavailable", 95 NumRetries: &wrapperspb.UInt32Value{Value: 1}, 96 }, 97 errs: []codes.Code{codes.ResourceExhausted, codes.Unavailable}, 98 routePolicy: nil, 99 tryAgainErr: codes.ResourceExhausted, 100 errWant: codes.Unavailable, 101 }, { 102 name: "virtualHost only", 103 vhPolicy: &v3routepb.RetryPolicy{ 104 RetryOn: "resource-exhausted, unavailable", 105 NumRetries: &wrapperspb.UInt32Value{Value: 2}, 106 }, 107 errs: []codes.Code{codes.ResourceExhausted, codes.Unavailable}, 108 routePolicy: nil, 109 tryAgainErr: codes.Unavailable, 110 errWant: codes.OK, 111 }, { 112 name: "virtualHost+route, fail", 113 vhPolicy: &v3routepb.RetryPolicy{ 114 RetryOn: "resource-exhausted,unavailable", 115 NumRetries: &wrapperspb.UInt32Value{Value: 2}, 116 }, 117 routePolicy: &v3routepb.RetryPolicy{ 118 RetryOn: "resource-exhausted", 119 NumRetries: &wrapperspb.UInt32Value{Value: 2}, 120 }, 121 errs: []codes.Code{codes.ResourceExhausted, codes.Unavailable}, 122 tryAgainErr: codes.OK, 123 errWant: codes.Unavailable, 124 }, { 125 name: "virtualHost+route", 126 vhPolicy: &v3routepb.RetryPolicy{ 127 RetryOn: "resource-exhausted", 128 NumRetries: &wrapperspb.UInt32Value{Value: 2}, 129 }, 130 routePolicy: &v3routepb.RetryPolicy{ 131 RetryOn: "unavailable", 132 NumRetries: &wrapperspb.UInt32Value{Value: 2}, 133 }, 134 errs: []codes.Code{codes.Unavailable}, 135 tryAgainErr: codes.Unavailable, 136 errWant: codes.OK, 137 }, { 138 name: "virtualHost+route, not enough attempts", 139 vhPolicy: &v3routepb.RetryPolicy{ 140 RetryOn: "unavailable", 141 NumRetries: &wrapperspb.UInt32Value{Value: 2}, 142 }, 143 routePolicy: &v3routepb.RetryPolicy{ 144 RetryOn: "unavailable", 145 NumRetries: &wrapperspb.UInt32Value{Value: 1}, 146 }, 147 errs: []codes.Code{codes.Unavailable, codes.Unavailable}, 148 tryAgainErr: codes.OK, 149 errWant: codes.Unavailable, 150 }} 151 152 for _, tc := range testCases { 153 t.Run(tc.name, func(t *testing.T) { 154 errs = tc.errs 155 156 // Confirm tryAgainErr is correct before updating resources. 157 ctr = 0 158 _, err := client.EmptyCall(ctx, &testpb.Empty{}) 159 if code := status.Code(err); code != tc.tryAgainErr { 160 t.Fatalf("with old retry policy: EmptyCall() = _, %v; want _, %v", err, tc.tryAgainErr) 161 } 162 163 resources.Routes[0].VirtualHosts[0].RetryPolicy = tc.vhPolicy 164 resources.Routes[0].VirtualHosts[0].Routes[0].GetRoute().RetryPolicy = tc.routePolicy 165 if err := managementServer.Update(ctx, resources); err != nil { 166 t.Fatal(err) 167 } 168 169 for { 170 ctr = 0 171 _, err := client.EmptyCall(ctx, &testpb.Empty{}) 172 if code := status.Code(err); code == tc.tryAgainErr { 173 continue 174 } else if code != tc.errWant { 175 t.Fatalf("rpc EmptyCall() = _, %v; want _, %v", err, tc.errWant) 176 } 177 break 178 } 179 }) 180 } 181 }