go.uber.org/yarpc@v1.72.1/encoding/protobuf/testing/testing_test.go (about) 1 // Copyright (c) 2022 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package testing 22 23 import ( 24 "context" 25 "io" 26 "testing" 27 28 "google.golang.org/grpc/codes" 29 "google.golang.org/grpc/status" 30 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 "go.uber.org/yarpc" 34 "go.uber.org/yarpc/api/transport" 35 "go.uber.org/yarpc/encoding/protobuf" 36 "go.uber.org/yarpc/internal/grpcctx" 37 "go.uber.org/yarpc/internal/prototest/example" 38 "go.uber.org/yarpc/internal/prototest/examplepb" 39 "go.uber.org/yarpc/internal/prototest/exampleutil" 40 "go.uber.org/yarpc/internal/testtime" 41 "go.uber.org/yarpc/internal/testutils" 42 intyarpcerrors "go.uber.org/yarpc/internal/yarpcerrors" 43 "go.uber.org/yarpc/yarpcerrors" 44 ) 45 46 func TestIntegration(t *testing.T) { 47 t.Parallel() 48 for _, transportType := range testutils.AllTransportTypes { 49 transportType := transportType 50 t.Run(transportType.String(), func(t *testing.T) { testIntegrationForTransportType(t, transportType) }) 51 } 52 } 53 54 func testIntegrationForTransportType(t *testing.T, transportType testutils.TransportType) { 55 expectedStreamingHeaders := transport.NewHeaders().With("firstTestKey", "firstTestValue") 56 keyValueYARPCServer := example.NewKeyValueYARPCServer() 57 fooYARPCServer := example.NewFooYARPCServer(expectedStreamingHeaders) 58 assert.NoError( 59 t, 60 exampleutil.WithClients( 61 transportType, 62 keyValueYARPCServer, 63 fooYARPCServer, 64 nil, 65 func(clients *exampleutil.Clients) error { 66 testIntegration(t, transportType, clients, keyValueYARPCServer, expectedStreamingHeaders) 67 return nil 68 }, 69 ), 70 ) 71 } 72 73 func testIntegration( 74 t *testing.T, 75 ttype testutils.TransportType, 76 clients *exampleutil.Clients, 77 keyValueYARPCServer *example.KeyValueYARPCServer, 78 expectedStreamingHeaders transport.Headers, 79 ) { 80 keyValueYARPCServer.SetNextError(intyarpcerrors.NewWithNamef(yarpcerrors.CodeUnknown, "foo-bar", "baz")) 81 err := setValue(clients.KeyValueYARPCClient, "foo", "bar") 82 assert.Equal(t, intyarpcerrors.NewWithNamef(yarpcerrors.CodeUnknown, "foo-bar", "baz"), err) 83 keyValueYARPCServer.SetNextError(intyarpcerrors.NewWithNamef(yarpcerrors.CodeUnknown, "foo-bar", "baz")) 84 err = setValueGRPC(clients.KeyValueGRPCClient, clients.ContextWrapper, "foo", "bar") 85 assert.Equal(t, status.Error(codes.Unknown, "foo-bar: baz"), err) 86 87 t.Run("error_details", func(t *testing.T) { 88 if ttype == testutils.TransportTypeTChannel { 89 t.Skip("TChannel does not support error details") 90 } 91 92 if ttype == testutils.TransportTypeHTTP { 93 // @todo internal code: RPC-2065 94 t.Skip("Error details for HTTP is currently broken") 95 } 96 97 keyValueYARPCServer.SetNextError(protobuf.NewError(yarpcerrors.CodeInternal, "foo-bar", protobuf.WithErrorDetails(&examplepb.EchoBothRequest{}))) 98 err = setValue(clients.KeyValueYARPCClient, "foo", "bar") 99 require.Len(t, protobuf.GetErrorDetails(err), 1) 100 assert.Equal(t, protobuf.GetErrorDetails(err)[0], &examplepb.EchoBothRequest{}) 101 assert.Equal(t, yarpcerrors.FromError(err).Code(), yarpcerrors.CodeInternal) 102 assert.Equal(t, yarpcerrors.FromError(err).Message(), "foo-bar") 103 104 keyValueYARPCServer.SetNextError(protobuf.NewError(yarpcerrors.CodeInternal, "hello world")) 105 err = setValue(clients.KeyValueYARPCClient, "foo", "bar") 106 assert.Equal(t, yarpcerrors.CodeInternal, yarpcerrors.FromError(err).Code()) 107 assert.Equal(t, "hello world", yarpcerrors.FromError(err).Message()) 108 }) 109 110 assert.NoError(t, setValue(clients.KeyValueYARPCClient, "foo", "")) 111 112 _, err = getValue(clients.KeyValueYARPCClient, "foo") 113 assert.Equal(t, yarpcerrors.Newf(yarpcerrors.CodeNotFound, "foo"), err) 114 _, err = getValueGRPC(clients.KeyValueGRPCClient, clients.ContextWrapper, "foo") 115 assert.Equal(t, status.Error(codes.NotFound, "foo"), err) 116 _, err = getValue(clients.KeyValueYARPCJSONClient, "foo") 117 assert.Equal(t, yarpcerrors.Newf(yarpcerrors.CodeNotFound, "foo"), err) 118 119 assert.NoError(t, setValue(clients.KeyValueYARPCClient, "foo", "bar")) 120 value, err := getValue(clients.KeyValueYARPCClient, "foo") 121 assert.NoError(t, err) 122 assert.Equal(t, "bar", value) 123 124 assert.NoError(t, setValue(clients.KeyValueYARPCJSONClient, "foo", "baz")) 125 value, err = getValue(clients.KeyValueYARPCJSONClient, "foo") 126 assert.NoError(t, err) 127 assert.Equal(t, "baz", value) 128 129 keyValueYARPCServer.SetNextError(yarpcerrors.Newf(yarpcerrors.CodeFailedPrecondition, "baz")) 130 value, err = getValue(clients.KeyValueYARPCClient, "foo") 131 assert.Equal(t, yarpcerrors.Newf(yarpcerrors.CodeFailedPrecondition, "baz"), err) 132 assert.Equal(t, "baz", value) 133 134 assert.NoError(t, setValueGRPC(clients.KeyValueGRPCClient, clients.ContextWrapper, "foo", "barGRPC")) 135 value, err = getValueGRPC(clients.KeyValueGRPCClient, clients.ContextWrapper, "foo") 136 assert.NoError(t, err) 137 assert.Equal(t, "barGRPC", value) 138 139 assert.NoError(t, setValue(clients.KeyValueYARPCClient, "foo", "")) 140 _, err = getValue(clients.KeyValueYARPCClient, "foo") 141 assert.Error(t, err) 142 143 assert.NoError(t, setValue(clients.KeyValueYARPCClient, "foo", "baz")) 144 assert.NoError(t, setValue(clients.KeyValueYARPCClient, "baz", "bat")) 145 value, err = getValue(clients.KeyValueYARPCClient, "foo") 146 assert.NoError(t, err) 147 assert.Equal(t, "baz", value) 148 value, err = getValue(clients.KeyValueYARPCClient, "baz") 149 assert.NoError(t, err) 150 assert.Equal(t, "bat", value) 151 152 contextWrapper := clients.ContextWrapper 153 streamOptions := make([]yarpc.CallOption, 0, expectedStreamingHeaders.Len()) 154 for k, v := range expectedStreamingHeaders.Items() { 155 streamOptions = append(streamOptions, yarpc.WithHeader(k, v)) 156 contextWrapper = contextWrapper.WithHeader(k, v) 157 } 158 159 messages := []string{"foo", "bar", "baz"} 160 gotMessages, err := echoOut(clients.FooYARPCClient, messages, streamOptions...) 161 assert.NoError(t, err) 162 assert.Equal(t, messages, gotMessages) 163 164 gotMessages, err = echoIn(clients.FooYARPCClient, "foo", 3, streamOptions...) 165 assert.NoError(t, err) 166 assert.Equal(t, []string{"foo", "foo", "foo"}, gotMessages) 167 168 gotMessages, err = echoBoth(clients.FooYARPCClient, "foo", 2, 2, streamOptions...) 169 assert.NoError(t, err) 170 assert.Equal(t, []string{"foo", "foo", "foo", "foo"}, gotMessages) 171 172 gotMessages, err = echoOutGRPC(clients.FooGRPCClient, contextWrapper, messages) 173 assert.NoError(t, err) 174 assert.Equal(t, messages, gotMessages) 175 176 gotMessages, err = echoInGRPC(clients.FooGRPCClient, contextWrapper, "foo", 3) 177 assert.NoError(t, err) 178 assert.Equal(t, []string{"foo", "foo", "foo"}, gotMessages) 179 180 gotMessages, err = echoBothGRPC(clients.FooGRPCClient, contextWrapper, "foo", 2, 2) 181 assert.NoError(t, err) 182 assert.Equal(t, []string{"foo", "foo", "foo", "foo"}, gotMessages) 183 } 184 185 func getValue(keyValueYARPCClient examplepb.KeyValueYARPCClient, key string, options ...yarpc.CallOption) (string, error) { 186 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 187 defer cancel() 188 response, err := keyValueYARPCClient.GetValue(ctx, &examplepb.GetValueRequest{Key: key}, options...) 189 if response != nil { 190 return response.Value, err 191 } 192 return "", err 193 } 194 195 func setValue(keyValueYARPCClient examplepb.KeyValueYARPCClient, key string, value string, options ...yarpc.CallOption) error { 196 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 197 defer cancel() 198 _, err := keyValueYARPCClient.SetValue(ctx, &examplepb.SetValueRequest{Key: key, Value: value}, options...) 199 return err 200 } 201 202 func getValueGRPC(keyValueGRPCClient examplepb.KeyValueClient, contextWrapper *grpcctx.ContextWrapper, key string) (string, error) { 203 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 204 defer cancel() 205 response, err := keyValueGRPCClient.GetValue(contextWrapper.Wrap(ctx), &examplepb.GetValueRequest{Key: key}) 206 if response != nil { 207 return response.Value, err 208 } 209 return "", err 210 } 211 212 func setValueGRPC(keyValueGRPCClient examplepb.KeyValueClient, contextWrapper *grpcctx.ContextWrapper, key string, value string) error { 213 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 214 defer cancel() 215 _, err := keyValueGRPCClient.SetValue(contextWrapper.Wrap(ctx), &examplepb.SetValueRequest{Key: key, Value: value}) 216 return err 217 } 218 219 func echoOut(fooYARPCClient examplepb.FooYARPCClient, messages []string, options ...yarpc.CallOption) ([]string, error) { 220 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 221 defer cancel() 222 client, err := fooYARPCClient.EchoOut(ctx, options...) 223 if err != nil { 224 return nil, err 225 } 226 for _, message := range messages { 227 if err := client.Send(&examplepb.EchoOutRequest{Message: message}); err != nil { 228 return nil, err 229 } 230 } 231 response, err := client.CloseAndRecv() 232 if err != nil { 233 return nil, err 234 } 235 return response.AllMessages, nil 236 } 237 238 func echoIn(fooYARPCClient examplepb.FooYARPCClient, message string, numResponses int, options ...yarpc.CallOption) ([]string, error) { 239 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 240 defer cancel() 241 client, err := fooYARPCClient.EchoIn(ctx, &examplepb.EchoInRequest{Message: message, NumResponses: int64(numResponses)}, options...) 242 if err != nil { 243 return nil, err 244 } 245 var messages []string 246 for response, err := client.Recv(); err != io.EOF; response, err = client.Recv() { 247 if err != nil { 248 return nil, err 249 } 250 messages = append(messages, response.Message) 251 } 252 return messages, nil 253 } 254 255 func echoBoth(fooYARPCClient examplepb.FooYARPCClient, message string, numResponses int, count int, options ...yarpc.CallOption) ([]string, error) { 256 ctx, cancel := context.WithTimeout(context.Background(), testtime.Second) 257 defer cancel() 258 client, err := fooYARPCClient.EchoBoth(ctx, options...) 259 if err != nil { 260 return nil, err 261 } 262 263 var messages []string 264 var recvErr error 265 done := make(chan struct{}) 266 go func() { 267 for response, err := client.Recv(); err != io.EOF; response, err = client.Recv() { 268 if err != nil { 269 recvErr = err 270 break 271 } 272 messages = append(messages, response.Message) 273 } 274 close(done) 275 }() 276 277 for i := 0; i < count; i++ { 278 if err := client.Send(&examplepb.EchoBothRequest{Message: message, NumResponses: int64(numResponses)}); err != nil { 279 return nil, err 280 } 281 } 282 if err := client.CloseSend(); err != nil { 283 return nil, err 284 } 285 286 <-done 287 return messages, recvErr 288 } 289 290 func echoOutGRPC(fooClient examplepb.FooClient, contextWrapper *grpcctx.ContextWrapper, messages []string) ([]string, error) { 291 client, err := fooClient.EchoOut(contextWrapper.Wrap(context.Background())) 292 if err != nil { 293 return nil, err 294 } 295 for _, message := range messages { 296 if err := client.Send(&examplepb.EchoOutRequest{Message: message}); err != nil { 297 return nil, err 298 } 299 } 300 response, err := client.CloseAndRecv() 301 if err != nil { 302 return nil, err 303 } 304 return response.AllMessages, nil 305 } 306 307 func echoInGRPC(fooClient examplepb.FooClient, contextWrapper *grpcctx.ContextWrapper, message string, numResponses int) ([]string, error) { 308 client, err := fooClient.EchoIn(contextWrapper.Wrap(context.Background()), &examplepb.EchoInRequest{Message: message, NumResponses: int64(numResponses)}) 309 if err != nil { 310 return nil, err 311 } 312 var messages []string 313 for response, err := client.Recv(); err != io.EOF; response, err = client.Recv() { 314 if err != nil { 315 return nil, err 316 } 317 messages = append(messages, response.Message) 318 } 319 return messages, nil 320 } 321 322 func echoBothGRPC(fooClient examplepb.FooClient, contextWrapper *grpcctx.ContextWrapper, message string, numResponses int, count int) ([]string, error) { 323 client, err := fooClient.EchoBoth(contextWrapper.Wrap(context.Background())) 324 if err != nil { 325 return nil, err 326 } 327 328 var messages []string 329 var recvErr error 330 done := make(chan struct{}) 331 go func() { 332 for response, err := client.Recv(); err != io.EOF; response, err = client.Recv() { 333 if err != nil { 334 recvErr = err 335 break 336 } 337 messages = append(messages, response.Message) 338 } 339 close(done) 340 }() 341 342 for i := 0; i < count; i++ { 343 if err := client.Send(&examplepb.EchoBothRequest{Message: message, NumResponses: int64(numResponses)}); err != nil { 344 return nil, err 345 } 346 } 347 if err := client.CloseSend(); err != nil { 348 return nil, err 349 } 350 351 <-done 352 return messages, recvErr 353 }