1
18
19 package test
20
21 import (
22 "context"
23 "strings"
24 "testing"
25 "time"
26
27 "google.golang.org/grpc"
28 "google.golang.org/grpc/balancer"
29 "google.golang.org/grpc/balancer/base"
30 "google.golang.org/grpc/codes"
31 "google.golang.org/grpc/connectivity"
32 "google.golang.org/grpc/internal/balancer/stub"
33 iresolver "google.golang.org/grpc/internal/resolver"
34 "google.golang.org/grpc/internal/stubserver"
35 testpb "google.golang.org/grpc/interop/grpc_testing"
36 "google.golang.org/grpc/resolver"
37 "google.golang.org/grpc/resolver/manual"
38 "google.golang.org/grpc/status"
39 )
40
41 func (s) TestConfigSelectorStatusCodes(t *testing.T) {
42 testCases := []struct {
43 name string
44 csErr error
45 want error
46 }{{
47 name: "legal status code",
48 csErr: status.Errorf(codes.Unavailable, "this error is fine"),
49 want: status.Errorf(codes.Unavailable, "this error is fine"),
50 }, {
51 name: "illegal status code",
52 csErr: status.Errorf(codes.NotFound, "this error is bad"),
53 want: status.Errorf(codes.Internal, "this error is bad"),
54 }}
55
56 for _, tc := range testCases {
57 t.Run(tc.name, func(t *testing.T) {
58 ss := &stubserver.StubServer{
59 EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
60 return &testpb.Empty{}, nil
61 },
62 }
63 ss.R = manual.NewBuilderWithScheme("confSel")
64
65 if err := ss.Start(nil); err != nil {
66 t.Fatalf("Error starting endpoint server: %v", err)
67 }
68 defer ss.Stop()
69
70 state := iresolver.SetConfigSelector(resolver.State{
71 Addresses: []resolver.Address{{Addr: ss.Address}},
72 ServiceConfig: parseServiceConfig(t, ss.R, "{}"),
73 }, funcConfigSelector{
74 f: func(i iresolver.RPCInfo) (*iresolver.RPCConfig, error) {
75 return nil, tc.csErr
76 },
77 })
78 ss.R.UpdateState(state)
79
80 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
81 defer cancel()
82 if _, err := ss.Client.EmptyCall(ctx, &testpb.Empty{}); status.Code(err) != status.Code(tc.want) || !strings.Contains(err.Error(), status.Convert(tc.want).Message()) {
83 t.Fatalf("client.EmptyCall(_, _) = _, %v; want _, %v", err, tc.want)
84 }
85 })
86 }
87 }
88
89 func (s) TestPickerStatusCodes(t *testing.T) {
90 testCases := []struct {
91 name string
92 pickerErr error
93 want error
94 }{{
95 name: "legal status code",
96 pickerErr: status.Errorf(codes.Unavailable, "this error is fine"),
97 want: status.Errorf(codes.Unavailable, "this error is fine"),
98 }, {
99 name: "illegal status code",
100 pickerErr: status.Errorf(codes.NotFound, "this error is bad"),
101 want: status.Errorf(codes.Internal, "this error is bad"),
102 }}
103
104 for _, tc := range testCases {
105 t.Run(tc.name, func(t *testing.T) {
106 ss := &stubserver.StubServer{
107 EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
108 return &testpb.Empty{}, nil
109 },
110 }
111
112 if err := ss.Start(nil); err != nil {
113 t.Fatalf("Error starting endpoint server: %v", err)
114 }
115 defer ss.Stop()
116
117
118
119 sbf := stub.BalancerFuncs{
120 UpdateClientConnState: func(d *stub.BalancerData, _ balancer.ClientConnState) error {
121 d.ClientConn.UpdateState(balancer.State{
122 ConnectivityState: connectivity.TransientFailure,
123 Picker: base.NewErrPicker(tc.pickerErr),
124 })
125 return nil
126 },
127 }
128 stub.Register("testPickerStatusCodesBalancer", sbf)
129
130 ss.NewServiceConfig(`{"loadBalancingConfig": [{"testPickerStatusCodesBalancer":{}}] }`)
131
132
133 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
134 defer cancel()
135
136 var lastErr error
137 for ctx.Err() == nil {
138 if _, lastErr = ss.Client.EmptyCall(ctx, &testpb.Empty{}); status.Code(lastErr) == status.Code(tc.want) && strings.Contains(lastErr.Error(), status.Convert(tc.want).Message()) {
139
140 return
141 }
142 time.Sleep(time.Millisecond)
143 }
144
145 t.Fatalf("client.EmptyCall(_, _) = _, %v; want _, %v", lastErr, tc.want)
146 })
147 }
148 }
149
150 func (s) TestCallCredsFromDialOptionsStatusCodes(t *testing.T) {
151 testCases := []struct {
152 name string
153 credsErr error
154 want error
155 }{{
156 name: "legal status code",
157 credsErr: status.Errorf(codes.Unavailable, "this error is fine"),
158 want: status.Errorf(codes.Unavailable, "this error is fine"),
159 }, {
160 name: "illegal status code",
161 credsErr: status.Errorf(codes.NotFound, "this error is bad"),
162 want: status.Errorf(codes.Internal, "this error is bad"),
163 }}
164
165 for _, tc := range testCases {
166 t.Run(tc.name, func(t *testing.T) {
167 ss := &stubserver.StubServer{
168 EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
169 return &testpb.Empty{}, nil
170 },
171 }
172
173 errChan := make(chan error, 1)
174 creds := &testPerRPCCredentials{errChan: errChan}
175
176 if err := ss.Start(nil, grpc.WithPerRPCCredentials(creds)); err != nil {
177 t.Fatalf("Error starting endpoint server: %v", err)
178 }
179 defer ss.Stop()
180
181 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
182 defer cancel()
183
184 errChan <- tc.credsErr
185
186 if _, err := ss.Client.EmptyCall(ctx, &testpb.Empty{}); status.Code(err) != status.Code(tc.want) || !strings.Contains(err.Error(), status.Convert(tc.want).Message()) {
187 t.Fatalf("client.EmptyCall(_, _) = _, %v; want _, %v", err, tc.want)
188 }
189 })
190 }
191 }
192
193 func (s) TestCallCredsFromCallOptionsStatusCodes(t *testing.T) {
194 testCases := []struct {
195 name string
196 credsErr error
197 want error
198 }{{
199 name: "legal status code",
200 credsErr: status.Errorf(codes.Unavailable, "this error is fine"),
201 want: status.Errorf(codes.Unavailable, "this error is fine"),
202 }, {
203 name: "illegal status code",
204 credsErr: status.Errorf(codes.NotFound, "this error is bad"),
205 want: status.Errorf(codes.Internal, "this error is bad"),
206 }}
207
208 for _, tc := range testCases {
209 t.Run(tc.name, func(t *testing.T) {
210 ss := &stubserver.StubServer{
211 EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
212 return &testpb.Empty{}, nil
213 },
214 }
215
216 errChan := make(chan error, 1)
217 creds := &testPerRPCCredentials{errChan: errChan}
218
219 if err := ss.Start(nil); err != nil {
220 t.Fatalf("Error starting endpoint server: %v", err)
221 }
222 defer ss.Stop()
223
224 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
225 defer cancel()
226
227 errChan <- tc.credsErr
228
229 if _, err := ss.Client.EmptyCall(ctx, &testpb.Empty{}, grpc.PerRPCCredentials(creds)); status.Code(err) != status.Code(tc.want) || !strings.Contains(err.Error(), status.Convert(tc.want).Message()) {
230 t.Fatalf("client.EmptyCall(_, _) = _, %v; want _, %v", err, tc.want)
231 }
232 })
233 }
234 }
235
View as plain text