github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/Godeps/_workspace/src/google.golang.org/grpc/interop/test_utils.go (about) 1 /* 2 * 3 * Copyright 2014, Google Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following disclaimer 14 * in the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Google Inc. nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34 package interop 35 36 import ( 37 "fmt" 38 "io" 39 "io/ioutil" 40 "strings" 41 "time" 42 43 "github.com/golang/protobuf/proto" 44 "golang.org/x/net/context" 45 "golang.org/x/oauth2" 46 "golang.org/x/oauth2/google" 47 "google.golang.org/grpc" 48 "google.golang.org/grpc/codes" 49 "google.golang.org/grpc/grpclog" 50 testpb "google.golang.org/grpc/interop/grpc_testing" 51 "google.golang.org/grpc/metadata" 52 ) 53 54 var ( 55 reqSizes = []int{27182, 8, 1828, 45904} 56 respSizes = []int{31415, 9, 2653, 58979} 57 largeReqSize = 271828 58 largeRespSize = 314159 59 ) 60 61 func clientNewPayload(t testpb.PayloadType, size int) *testpb.Payload { 62 if size < 0 { 63 grpclog.Fatalf("Requested a response with invalid length %d", size) 64 } 65 body := make([]byte, size) 66 switch t { 67 case testpb.PayloadType_COMPRESSABLE: 68 case testpb.PayloadType_UNCOMPRESSABLE: 69 grpclog.Fatalf("PayloadType UNCOMPRESSABLE is not supported") 70 default: 71 grpclog.Fatalf("Unsupported payload type: %d", t) 72 } 73 return &testpb.Payload{ 74 Type: t.Enum(), 75 Body: body, 76 } 77 } 78 79 // DoEmptyUnaryCall performs a unary RPC with empty request and response messages. 80 func DoEmptyUnaryCall(tc testpb.TestServiceClient) { 81 reply, err := tc.EmptyCall(context.Background(), &testpb.Empty{}) 82 if err != nil { 83 grpclog.Fatal("/TestService/EmptyCall RPC failed: ", err) 84 } 85 if !proto.Equal(&testpb.Empty{}, reply) { 86 grpclog.Fatalf("/TestService/EmptyCall receives %v, want %v", reply, testpb.Empty{}) 87 } 88 grpclog.Println("EmptyUnaryCall done") 89 } 90 91 // DoLargeUnaryCall performs a unary RPC with large payload in the request and response. 92 func DoLargeUnaryCall(tc testpb.TestServiceClient) { 93 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 94 req := &testpb.SimpleRequest{ 95 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 96 ResponseSize: proto.Int32(int32(largeRespSize)), 97 Payload: pl, 98 } 99 reply, err := tc.UnaryCall(context.Background(), req) 100 if err != nil { 101 grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) 102 } 103 t := reply.GetPayload().GetType() 104 s := len(reply.GetPayload().GetBody()) 105 if t != testpb.PayloadType_COMPRESSABLE || s != largeRespSize { 106 grpclog.Fatalf("Got the reply with type %d len %d; want %d, %d", t, s, testpb.PayloadType_COMPRESSABLE, largeRespSize) 107 } 108 grpclog.Println("LargeUnaryCall done") 109 } 110 111 // DoClientStreaming performs a client streaming RPC. 112 func DoClientStreaming(tc testpb.TestServiceClient) { 113 stream, err := tc.StreamingInputCall(context.Background()) 114 if err != nil { 115 grpclog.Fatalf("%v.StreamingInputCall(_) = _, %v", tc, err) 116 } 117 var sum int 118 for _, s := range reqSizes { 119 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, s) 120 req := &testpb.StreamingInputCallRequest{ 121 Payload: pl, 122 } 123 if err := stream.Send(req); err != nil { 124 grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) 125 } 126 sum += s 127 grpclog.Printf("Sent a request of size %d, aggregated size %d", s, sum) 128 129 } 130 reply, err := stream.CloseAndRecv() 131 if err != nil { 132 grpclog.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil) 133 } 134 if reply.GetAggregatedPayloadSize() != int32(sum) { 135 grpclog.Fatalf("%v.CloseAndRecv().GetAggregatePayloadSize() = %v; want %v", stream, reply.GetAggregatedPayloadSize(), sum) 136 } 137 grpclog.Println("ClientStreaming done") 138 } 139 140 // DoServerStreaming performs a server streaming RPC. 141 func DoServerStreaming(tc testpb.TestServiceClient) { 142 respParam := make([]*testpb.ResponseParameters, len(respSizes)) 143 for i, s := range respSizes { 144 respParam[i] = &testpb.ResponseParameters{ 145 Size: proto.Int32(int32(s)), 146 } 147 } 148 req := &testpb.StreamingOutputCallRequest{ 149 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 150 ResponseParameters: respParam, 151 } 152 stream, err := tc.StreamingOutputCall(context.Background(), req) 153 if err != nil { 154 grpclog.Fatalf("%v.StreamingOutputCall(_) = _, %v", tc, err) 155 } 156 var rpcStatus error 157 var respCnt int 158 var index int 159 for { 160 reply, err := stream.Recv() 161 if err != nil { 162 rpcStatus = err 163 break 164 } 165 t := reply.GetPayload().GetType() 166 if t != testpb.PayloadType_COMPRESSABLE { 167 grpclog.Fatalf("Got the reply of type %d, want %d", t, testpb.PayloadType_COMPRESSABLE) 168 } 169 size := len(reply.GetPayload().GetBody()) 170 if size != int(respSizes[index]) { 171 grpclog.Fatalf("Got reply body of length %d, want %d", size, respSizes[index]) 172 } 173 index++ 174 respCnt++ 175 } 176 if rpcStatus != io.EOF { 177 grpclog.Fatalf("Failed to finish the server streaming rpc: %v", err) 178 } 179 if respCnt != len(respSizes) { 180 grpclog.Fatalf("Got %d reply, want %d", len(respSizes), respCnt) 181 } 182 grpclog.Println("ServerStreaming done") 183 } 184 185 // DoPingPong performs ping-pong style bi-directional streaming RPC. 186 func DoPingPong(tc testpb.TestServiceClient) { 187 stream, err := tc.FullDuplexCall(context.Background()) 188 if err != nil { 189 grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) 190 } 191 var index int 192 for index < len(reqSizes) { 193 respParam := []*testpb.ResponseParameters{ 194 { 195 Size: proto.Int32(int32(respSizes[index])), 196 }, 197 } 198 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, reqSizes[index]) 199 req := &testpb.StreamingOutputCallRequest{ 200 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 201 ResponseParameters: respParam, 202 Payload: pl, 203 } 204 if err := stream.Send(req); err != nil { 205 grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) 206 } 207 reply, err := stream.Recv() 208 if err != nil { 209 grpclog.Fatalf("%v.Recv() = %v", stream, err) 210 } 211 t := reply.GetPayload().GetType() 212 if t != testpb.PayloadType_COMPRESSABLE { 213 grpclog.Fatalf("Got the reply of type %d, want %d", t, testpb.PayloadType_COMPRESSABLE) 214 } 215 size := len(reply.GetPayload().GetBody()) 216 if size != int(respSizes[index]) { 217 grpclog.Fatalf("Got reply body of length %d, want %d", size, respSizes[index]) 218 } 219 index++ 220 } 221 if err := stream.CloseSend(); err != nil { 222 grpclog.Fatalf("%v.CloseSend() got %v, want %v", stream, err, nil) 223 } 224 if _, err := stream.Recv(); err != io.EOF { 225 grpclog.Fatalf("%v failed to complele the ping pong test: %v", stream, err) 226 } 227 grpclog.Println("Pingpong done") 228 } 229 230 // DoEmptyStream sets up a bi-directional streaming with zero message. 231 func DoEmptyStream(tc testpb.TestServiceClient) { 232 stream, err := tc.FullDuplexCall(context.Background()) 233 if err != nil { 234 grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) 235 } 236 if err := stream.CloseSend(); err != nil { 237 grpclog.Fatalf("%v.CloseSend() got %v, want %v", stream, err, nil) 238 } 239 if _, err := stream.Recv(); err != io.EOF { 240 grpclog.Fatalf("%v failed to complete the empty stream test: %v", stream, err) 241 } 242 grpclog.Println("Emptystream done") 243 } 244 245 // DoTimeoutOnSleepingServer performs an RPC on a sleep server which causes RPC timeout. 246 func DoTimeoutOnSleepingServer(tc testpb.TestServiceClient) { 247 ctx, _ := context.WithTimeout(context.Background(), 1*time.Millisecond) 248 stream, err := tc.FullDuplexCall(ctx) 249 if err != nil { 250 if grpc.Code(err) == codes.DeadlineExceeded { 251 grpclog.Println("TimeoutOnSleepingServer done") 252 return 253 } 254 grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) 255 } 256 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, 27182) 257 req := &testpb.StreamingOutputCallRequest{ 258 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 259 Payload: pl, 260 } 261 if err := stream.Send(req); err != nil { 262 grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) 263 } 264 if _, err := stream.Recv(); grpc.Code(err) != codes.DeadlineExceeded { 265 grpclog.Fatalf("%v.Recv() = _, %v, want error code %d", stream, err, codes.DeadlineExceeded) 266 } 267 grpclog.Println("TimeoutOnSleepingServer done") 268 } 269 270 // DoComputeEngineCreds performs a unary RPC with compute engine auth. 271 func DoComputeEngineCreds(tc testpb.TestServiceClient, serviceAccount, oauthScope string) { 272 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 273 req := &testpb.SimpleRequest{ 274 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 275 ResponseSize: proto.Int32(int32(largeRespSize)), 276 Payload: pl, 277 FillUsername: proto.Bool(true), 278 FillOauthScope: proto.Bool(true), 279 } 280 reply, err := tc.UnaryCall(context.Background(), req) 281 if err != nil { 282 grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) 283 } 284 user := reply.GetUsername() 285 scope := reply.GetOauthScope() 286 if user != serviceAccount { 287 grpclog.Fatalf("Got user name %q, want %q.", user, serviceAccount) 288 } 289 if !strings.Contains(oauthScope, scope) { 290 grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) 291 } 292 grpclog.Println("ComputeEngineCreds done") 293 } 294 295 func getServiceAccountJSONKey(keyFile string) []byte { 296 jsonKey, err := ioutil.ReadFile(keyFile) 297 if err != nil { 298 grpclog.Fatalf("Failed to read the service account key file: %v", err) 299 } 300 return jsonKey 301 } 302 303 // DoServiceAccountCreds performs a unary RPC with service account auth. 304 func DoServiceAccountCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScope string) { 305 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 306 req := &testpb.SimpleRequest{ 307 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 308 ResponseSize: proto.Int32(int32(largeRespSize)), 309 Payload: pl, 310 FillUsername: proto.Bool(true), 311 FillOauthScope: proto.Bool(true), 312 } 313 reply, err := tc.UnaryCall(context.Background(), req) 314 if err != nil { 315 grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) 316 } 317 jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) 318 user := reply.GetUsername() 319 scope := reply.GetOauthScope() 320 if !strings.Contains(string(jsonKey), user) { 321 grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) 322 } 323 if !strings.Contains(oauthScope, scope) { 324 grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) 325 } 326 grpclog.Println("ServiceAccountCreds done") 327 } 328 329 // DoJWTTokenCreds performs a unary RPC with JWT token auth. 330 func DoJWTTokenCreds(tc testpb.TestServiceClient, serviceAccountKeyFile string) { 331 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 332 req := &testpb.SimpleRequest{ 333 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 334 ResponseSize: proto.Int32(int32(largeRespSize)), 335 Payload: pl, 336 FillUsername: proto.Bool(true), 337 } 338 reply, err := tc.UnaryCall(context.Background(), req) 339 if err != nil { 340 grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) 341 } 342 jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) 343 user := reply.GetUsername() 344 if !strings.Contains(string(jsonKey), user) { 345 grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) 346 } 347 grpclog.Println("JWTtokenCreds done") 348 } 349 350 // GetToken obtains an OAUTH token from the input. 351 func GetToken(serviceAccountKeyFile string, oauthScope string) *oauth2.Token { 352 jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) 353 config, err := google.JWTConfigFromJSON(jsonKey, oauthScope) 354 if err != nil { 355 grpclog.Fatalf("Failed to get the config: %v", err) 356 } 357 token, err := config.TokenSource(context.Background()).Token() 358 if err != nil { 359 grpclog.Fatalf("Failed to get the token: %v", err) 360 } 361 return token 362 } 363 364 // DoOauth2TokenCreds performs a unary RPC with OAUTH2 token auth. 365 func DoOauth2TokenCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScope string) { 366 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 367 req := &testpb.SimpleRequest{ 368 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 369 ResponseSize: proto.Int32(int32(largeRespSize)), 370 Payload: pl, 371 FillUsername: proto.Bool(true), 372 FillOauthScope: proto.Bool(true), 373 } 374 reply, err := tc.UnaryCall(context.Background(), req) 375 if err != nil { 376 grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) 377 } 378 jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) 379 user := reply.GetUsername() 380 scope := reply.GetOauthScope() 381 if !strings.Contains(string(jsonKey), user) { 382 grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) 383 } 384 if !strings.Contains(oauthScope, scope) { 385 grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) 386 } 387 grpclog.Println("Oauth2TokenCreds done") 388 } 389 390 // DoPerRPCCreds performs a unary RPC with per RPC OAUTH2 token. 391 func DoPerRPCCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScope string) { 392 jsonKey := getServiceAccountJSONKey(serviceAccountKeyFile) 393 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 394 req := &testpb.SimpleRequest{ 395 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 396 ResponseSize: proto.Int32(int32(largeRespSize)), 397 Payload: pl, 398 FillUsername: proto.Bool(true), 399 FillOauthScope: proto.Bool(true), 400 } 401 token := GetToken(serviceAccountKeyFile, oauthScope) 402 kv := map[string]string{"authorization": token.TokenType + " " + token.AccessToken} 403 ctx := metadata.NewContext(context.Background(), metadata.MD{"authorization": []string{kv["authorization"]}}) 404 reply, err := tc.UnaryCall(ctx, req) 405 if err != nil { 406 grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err) 407 } 408 user := reply.GetUsername() 409 scope := reply.GetOauthScope() 410 if !strings.Contains(string(jsonKey), user) { 411 grpclog.Fatalf("Got user name %q which is NOT a substring of %q.", user, jsonKey) 412 } 413 if !strings.Contains(oauthScope, scope) { 414 grpclog.Fatalf("Got OAuth scope %q which is NOT a substring of %q.", scope, oauthScope) 415 } 416 grpclog.Println("PerRPCCreds done") 417 } 418 419 var ( 420 testMetadata = metadata.MD{ 421 "key1": []string{"value1"}, 422 "key2": []string{"value2"}, 423 } 424 ) 425 426 // DoCancelAfterBegin cancels the RPC after metadata has been sent but before payloads are sent. 427 func DoCancelAfterBegin(tc testpb.TestServiceClient) { 428 ctx, cancel := context.WithCancel(metadata.NewContext(context.Background(), testMetadata)) 429 stream, err := tc.StreamingInputCall(ctx) 430 if err != nil { 431 grpclog.Fatalf("%v.StreamingInputCall(_) = _, %v", tc, err) 432 } 433 cancel() 434 _, err = stream.CloseAndRecv() 435 if grpc.Code(err) != codes.Canceled { 436 grpclog.Fatalf("%v.CloseAndRecv() got error code %d, want %d", stream, grpc.Code(err), codes.Canceled) 437 } 438 grpclog.Println("CancelAfterBegin done") 439 } 440 441 // DoCancelAfterFirstResponse cancels the RPC after receiving the first message from the server. 442 func DoCancelAfterFirstResponse(tc testpb.TestServiceClient) { 443 ctx, cancel := context.WithCancel(context.Background()) 444 stream, err := tc.FullDuplexCall(ctx) 445 if err != nil { 446 grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err) 447 } 448 respParam := []*testpb.ResponseParameters{ 449 { 450 Size: proto.Int32(31415), 451 }, 452 } 453 pl := clientNewPayload(testpb.PayloadType_COMPRESSABLE, 27182) 454 req := &testpb.StreamingOutputCallRequest{ 455 ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(), 456 ResponseParameters: respParam, 457 Payload: pl, 458 } 459 if err := stream.Send(req); err != nil { 460 grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err) 461 } 462 if _, err := stream.Recv(); err != nil { 463 grpclog.Fatalf("%v.Recv() = %v", stream, err) 464 } 465 cancel() 466 if _, err := stream.Recv(); grpc.Code(err) != codes.Canceled { 467 grpclog.Fatalf("%v compleled with error code %d, want %d", stream, grpc.Code(err), codes.Canceled) 468 } 469 grpclog.Println("CancelAfterFirstResponse done") 470 } 471 472 type testServer struct { 473 } 474 475 // NewTestServer creates a test server for test service. 476 func NewTestServer() testpb.TestServiceServer { 477 return &testServer{} 478 } 479 480 func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { 481 return new(testpb.Empty), nil 482 } 483 484 func serverNewPayload(t testpb.PayloadType, size int32) (*testpb.Payload, error) { 485 if size < 0 { 486 return nil, fmt.Errorf("requested a response with invalid length %d", size) 487 } 488 body := make([]byte, size) 489 switch t { 490 case testpb.PayloadType_COMPRESSABLE: 491 case testpb.PayloadType_UNCOMPRESSABLE: 492 return nil, fmt.Errorf("payloadType UNCOMPRESSABLE is not supported") 493 default: 494 return nil, fmt.Errorf("unsupported payload type: %d", t) 495 } 496 return &testpb.Payload{ 497 Type: t.Enum(), 498 Body: body, 499 }, nil 500 } 501 502 func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 503 pl, err := serverNewPayload(in.GetResponseType(), in.GetResponseSize()) 504 if err != nil { 505 return nil, err 506 } 507 return &testpb.SimpleResponse{ 508 Payload: pl, 509 }, nil 510 } 511 512 func (s *testServer) StreamingOutputCall(args *testpb.StreamingOutputCallRequest, stream testpb.TestService_StreamingOutputCallServer) error { 513 cs := args.GetResponseParameters() 514 for _, c := range cs { 515 if us := c.GetIntervalUs(); us > 0 { 516 time.Sleep(time.Duration(us) * time.Microsecond) 517 } 518 pl, err := serverNewPayload(args.GetResponseType(), c.GetSize()) 519 if err != nil { 520 return err 521 } 522 if err := stream.Send(&testpb.StreamingOutputCallResponse{ 523 Payload: pl, 524 }); err != nil { 525 return err 526 } 527 } 528 return nil 529 } 530 531 func (s *testServer) StreamingInputCall(stream testpb.TestService_StreamingInputCallServer) error { 532 var sum int 533 for { 534 in, err := stream.Recv() 535 if err == io.EOF { 536 return stream.SendAndClose(&testpb.StreamingInputCallResponse{ 537 AggregatedPayloadSize: proto.Int32(int32(sum)), 538 }) 539 } 540 if err != nil { 541 return err 542 } 543 p := in.GetPayload().GetBody() 544 sum += len(p) 545 } 546 } 547 548 func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { 549 for { 550 in, err := stream.Recv() 551 if err == io.EOF { 552 // read done. 553 return nil 554 } 555 if err != nil { 556 return err 557 } 558 cs := in.GetResponseParameters() 559 for _, c := range cs { 560 if us := c.GetIntervalUs(); us > 0 { 561 time.Sleep(time.Duration(us) * time.Microsecond) 562 } 563 pl, err := serverNewPayload(in.GetResponseType(), c.GetSize()) 564 if err != nil { 565 return err 566 } 567 if err := stream.Send(&testpb.StreamingOutputCallResponse{ 568 Payload: pl, 569 }); err != nil { 570 return err 571 } 572 } 573 } 574 } 575 576 func (s *testServer) HalfDuplexCall(stream testpb.TestService_HalfDuplexCallServer) error { 577 var msgBuf []*testpb.StreamingOutputCallRequest 578 for { 579 in, err := stream.Recv() 580 if err == io.EOF { 581 // read done. 582 break 583 } 584 if err != nil { 585 return err 586 } 587 msgBuf = append(msgBuf, in) 588 } 589 for _, m := range msgBuf { 590 cs := m.GetResponseParameters() 591 for _, c := range cs { 592 if us := c.GetIntervalUs(); us > 0 { 593 time.Sleep(time.Duration(us) * time.Microsecond) 594 } 595 pl, err := serverNewPayload(m.GetResponseType(), c.GetSize()) 596 if err != nil { 597 return err 598 } 599 if err := stream.Send(&testpb.StreamingOutputCallResponse{ 600 Payload: pl, 601 }); err != nil { 602 return err 603 } 604 } 605 } 606 return nil 607 }