google.golang.org/grpc@v1.62.1/test/goaway_test.go (about) 1 /* 2 * 3 * Copyright 2019 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 test 20 21 import ( 22 "context" 23 "io" 24 "net" 25 "strings" 26 "testing" 27 "time" 28 29 "golang.org/x/net/http2" 30 "google.golang.org/grpc" 31 "google.golang.org/grpc/codes" 32 "google.golang.org/grpc/connectivity" 33 "google.golang.org/grpc/credentials/insecure" 34 "google.golang.org/grpc/internal" 35 "google.golang.org/grpc/internal/grpcsync" 36 "google.golang.org/grpc/internal/grpctest" 37 "google.golang.org/grpc/internal/stubserver" 38 "google.golang.org/grpc/internal/testutils" 39 "google.golang.org/grpc/keepalive" 40 "google.golang.org/grpc/resolver" 41 "google.golang.org/grpc/resolver/manual" 42 "google.golang.org/grpc/status" 43 44 testgrpc "google.golang.org/grpc/interop/grpc_testing" 45 testpb "google.golang.org/grpc/interop/grpc_testing" 46 ) 47 48 // TestGracefulClientOnGoAway attempts to ensure that when the server sends a 49 // GOAWAY (in this test, by configuring max connection age on the server), a 50 // client will never see an error. This requires that the client is appraised 51 // of the GOAWAY and updates its state accordingly before the transport stops 52 // accepting new streams. If a subconn is chosen by a picker and receives the 53 // goaway before creating the stream, an error will occur, but upon transparent 54 // retry, the clientconn will ensure a ready subconn is chosen. 55 func (s) TestGracefulClientOnGoAway(t *testing.T) { 56 const maxConnAge = 100 * time.Millisecond 57 const testTime = maxConnAge * 10 58 59 ss := &stubserver.StubServer{ 60 EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { 61 return &testpb.Empty{}, nil 62 }, 63 } 64 65 s := grpc.NewServer(grpc.KeepaliveParams(keepalive.ServerParameters{MaxConnectionAge: maxConnAge})) 66 defer s.Stop() 67 testgrpc.RegisterTestServiceServer(s, ss) 68 69 lis, err := net.Listen("tcp", "localhost:0") 70 if err != nil { 71 t.Fatalf("Failed to create listener: %v", err) 72 } 73 go s.Serve(lis) 74 75 cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) 76 if err != nil { 77 t.Fatalf("Failed to dial server: %v", err) 78 } 79 defer cc.Close() 80 c := testgrpc.NewTestServiceClient(cc) 81 82 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 83 defer cancel() 84 85 endTime := time.Now().Add(testTime) 86 for time.Now().Before(endTime) { 87 if _, err := c.EmptyCall(ctx, &testpb.Empty{}); err != nil { 88 t.Fatalf("EmptyCall(_, _) = _, %v; want _, <nil>", err) 89 } 90 } 91 } 92 93 func (s) TestDetailedGoAwayErrorOnGracefulClosePropagatesToRPCError(t *testing.T) { 94 rpcDoneOnClient := make(chan struct{}) 95 ss := &stubserver.StubServer{ 96 FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { 97 <-rpcDoneOnClient 98 return status.Error(codes.Internal, "arbitrary status") 99 }, 100 } 101 sopts := []grpc.ServerOption{ 102 grpc.KeepaliveParams(keepalive.ServerParameters{ 103 MaxConnectionAge: time.Millisecond * 100, 104 MaxConnectionAgeGrace: time.Nanosecond, // ~instantaneously, but non-zero to avoid default 105 }), 106 } 107 if err := ss.Start(sopts); err != nil { 108 t.Fatalf("Error starting endpoint server: %v", err) 109 } 110 defer ss.Stop() 111 112 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 113 defer cancel() 114 stream, err := ss.Client.FullDuplexCall(ctx) 115 if err != nil { 116 t.Fatalf("%v.FullDuplexCall = _, %v, want _, <nil>", ss.Client, err) 117 } 118 const expectedErrorMessageSubstring = "received prior goaway: code: NO_ERROR" 119 _, err = stream.Recv() 120 close(rpcDoneOnClient) 121 if err == nil || !strings.Contains(err.Error(), expectedErrorMessageSubstring) { 122 t.Fatalf("%v.Recv() = _, %v, want _, rpc error containing substring: %q", stream, err, expectedErrorMessageSubstring) 123 } 124 } 125 126 func (s) TestDetailedGoAwayErrorOnAbruptClosePropagatesToRPCError(t *testing.T) { 127 grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"") 128 // set the min keepalive time very low so that this test can take 129 // a reasonable amount of time 130 prev := internal.KeepaliveMinPingTime 131 internal.KeepaliveMinPingTime = time.Millisecond 132 defer func() { internal.KeepaliveMinPingTime = prev }() 133 134 rpcDoneOnClient := make(chan struct{}) 135 ss := &stubserver.StubServer{ 136 FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { 137 <-rpcDoneOnClient 138 return status.Error(codes.Internal, "arbitrary status") 139 }, 140 } 141 sopts := []grpc.ServerOption{ 142 grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ 143 MinTime: time.Second * 1000, /* arbitrary, large value */ 144 }), 145 } 146 dopts := []grpc.DialOption{ 147 grpc.WithKeepaliveParams(keepalive.ClientParameters{ 148 Time: time.Millisecond, /* should trigger "too many pings" error quickly */ 149 Timeout: time.Second * 1000, /* arbitrary, large value */ 150 PermitWithoutStream: false, 151 }), 152 } 153 if err := ss.Start(sopts, dopts...); err != nil { 154 t.Fatalf("Error starting endpoint server: %v", err) 155 } 156 defer ss.Stop() 157 158 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 159 defer cancel() 160 stream, err := ss.Client.FullDuplexCall(ctx) 161 if err != nil { 162 t.Fatalf("%v.FullDuplexCall = _, %v, want _, <nil>", ss.Client, err) 163 } 164 const expectedErrorMessageSubstring = `received prior goaway: code: ENHANCE_YOUR_CALM, debug data: "too_many_pings"` 165 _, err = stream.Recv() 166 close(rpcDoneOnClient) 167 if err == nil || !strings.Contains(err.Error(), expectedErrorMessageSubstring) { 168 t.Fatalf("%v.Recv() = _, %v, want _, rpc error containing substring: |%v|", stream, err, expectedErrorMessageSubstring) 169 } 170 } 171 172 func (s) TestClientConnCloseAfterGoAwayWithActiveStream(t *testing.T) { 173 for _, e := range listTestEnv() { 174 if e.name == "handler-tls" { 175 continue 176 } 177 testClientConnCloseAfterGoAwayWithActiveStream(t, e) 178 } 179 } 180 181 func testClientConnCloseAfterGoAwayWithActiveStream(t *testing.T, e env) { 182 te := newTest(t, e) 183 te.startServer(&testServer{security: e.security}) 184 defer te.tearDown() 185 cc := te.clientConn() 186 tc := testgrpc.NewTestServiceClient(cc) 187 188 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 189 defer cancel() 190 if _, err := tc.FullDuplexCall(ctx); err != nil { 191 t.Fatalf("%v.FullDuplexCall(_) = _, %v, want _, <nil>", tc, err) 192 } 193 done := make(chan struct{}) 194 go func() { 195 te.srv.GracefulStop() 196 close(done) 197 }() 198 time.Sleep(50 * time.Millisecond) 199 cc.Close() 200 timeout := time.NewTimer(time.Second) 201 select { 202 case <-done: 203 case <-timeout.C: 204 t.Fatalf("Test timed-out.") 205 } 206 } 207 208 func (s) TestServerGoAway(t *testing.T) { 209 for _, e := range listTestEnv() { 210 if e.name == "handler-tls" { 211 continue 212 } 213 testServerGoAway(t, e) 214 } 215 } 216 217 func testServerGoAway(t *testing.T, e env) { 218 te := newTest(t, e) 219 te.userAgent = testAppUA 220 te.startServer(&testServer{security: e.security}) 221 defer te.tearDown() 222 223 cc := te.clientConn() 224 tc := testgrpc.NewTestServiceClient(cc) 225 // Finish an RPC to make sure the connection is good. 226 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 227 defer cancel() 228 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 229 t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err) 230 } 231 ch := make(chan struct{}) 232 go func() { 233 te.srv.GracefulStop() 234 close(ch) 235 }() 236 // Loop until the server side GoAway signal is propagated to the client. 237 for { 238 ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 239 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}); err != nil && status.Code(err) != codes.DeadlineExceeded { 240 cancel() 241 break 242 } 243 cancel() 244 } 245 // A new RPC should fail. 246 ctx, cancel = context.WithTimeout(context.Background(), defaultTestTimeout) 247 defer cancel() 248 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}); status.Code(err) != codes.Unavailable && status.Code(err) != codes.Internal { 249 t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want _, %s or %s", err, codes.Unavailable, codes.Internal) 250 } 251 <-ch 252 awaitNewConnLogOutput() 253 } 254 255 func (s) TestServerGoAwayPendingRPC(t *testing.T) { 256 for _, e := range listTestEnv() { 257 if e.name == "handler-tls" { 258 continue 259 } 260 testServerGoAwayPendingRPC(t, e) 261 } 262 } 263 264 func testServerGoAwayPendingRPC(t *testing.T, e env) { 265 te := newTest(t, e) 266 te.userAgent = testAppUA 267 te.declareLogNoise( 268 "transport: http2Client.notifyError got notified that the client transport was broken EOF", 269 "grpc: addrConn.transportMonitor exits due to: grpc: the connection is closing", 270 "grpc: addrConn.resetTransport failed to create client transport: connection error", 271 ) 272 te.startServer(&testServer{security: e.security}) 273 defer te.tearDown() 274 275 cc := te.clientConn() 276 tc := testgrpc.NewTestServiceClient(cc) 277 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 278 stream, err := tc.FullDuplexCall(ctx, grpc.WaitForReady(true)) 279 if err != nil { 280 t.Fatalf("%v.FullDuplexCall(_) = _, %v, want <nil>", tc, err) 281 } 282 // Finish an RPC to make sure the connection is good. 283 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 284 t.Fatalf("%v.EmptyCall(_, _, _) = _, %v, want _, <nil>", tc, err) 285 } 286 ch := make(chan struct{}) 287 go func() { 288 te.srv.GracefulStop() 289 close(ch) 290 }() 291 // Loop until the server side GoAway signal is propagated to the client. 292 start := time.Now() 293 errored := false 294 for time.Since(start) < time.Second { 295 ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 296 _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)) 297 cancel() 298 if err != nil { 299 errored = true 300 break 301 } 302 } 303 if !errored { 304 t.Fatalf("GoAway never received by client") 305 } 306 respParam := []*testpb.ResponseParameters{{Size: 1}} 307 payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(100)) 308 if err != nil { 309 t.Fatal(err) 310 } 311 req := &testpb.StreamingOutputCallRequest{ 312 ResponseType: testpb.PayloadType_COMPRESSABLE, 313 ResponseParameters: respParam, 314 Payload: payload, 315 } 316 // The existing RPC should be still good to proceed. 317 if err := stream.Send(req); err != nil { 318 t.Fatalf("%v.Send(_) = %v, want <nil>", stream, err) 319 } 320 if _, err := stream.Recv(); err != nil { 321 t.Fatalf("%v.Recv() = _, %v, want _, <nil>", stream, err) 322 } 323 // The RPC will run until canceled. 324 cancel() 325 <-ch 326 awaitNewConnLogOutput() 327 } 328 329 func (s) TestServerMultipleGoAwayPendingRPC(t *testing.T) { 330 for _, e := range listTestEnv() { 331 if e.name == "handler-tls" { 332 continue 333 } 334 testServerMultipleGoAwayPendingRPC(t, e) 335 } 336 } 337 338 func testServerMultipleGoAwayPendingRPC(t *testing.T, e env) { 339 te := newTest(t, e) 340 te.userAgent = testAppUA 341 te.declareLogNoise( 342 "transport: http2Client.notifyError got notified that the client transport was broken EOF", 343 "grpc: addrConn.transportMonitor exits due to: grpc: the connection is closing", 344 "grpc: addrConn.resetTransport failed to create client transport: connection error", 345 ) 346 te.startServer(&testServer{security: e.security}) 347 defer te.tearDown() 348 349 cc := te.clientConn() 350 tc := testgrpc.NewTestServiceClient(cc) 351 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 352 stream, err := tc.FullDuplexCall(ctx, grpc.WaitForReady(true)) 353 if err != nil { 354 t.Fatalf("%v.FullDuplexCall(_) = _, %v, want <nil>", tc, err) 355 } 356 // Finish an RPC to make sure the connection is good. 357 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 358 t.Fatalf("%v.EmptyCall(_, _, _) = _, %v, want _, <nil>", tc, err) 359 } 360 ch1 := make(chan struct{}) 361 go func() { 362 te.srv.GracefulStop() 363 close(ch1) 364 }() 365 ch2 := make(chan struct{}) 366 go func() { 367 te.srv.GracefulStop() 368 close(ch2) 369 }() 370 // Loop until the server side GoAway signal is propagated to the client. 371 372 for { 373 ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 374 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 375 cancel() 376 break 377 } 378 cancel() 379 } 380 select { 381 case <-ch1: 382 t.Fatal("GracefulStop() terminated early") 383 case <-ch2: 384 t.Fatal("GracefulStop() terminated early") 385 default: 386 } 387 respParam := []*testpb.ResponseParameters{ 388 { 389 Size: 1, 390 }, 391 } 392 payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(100)) 393 if err != nil { 394 t.Fatal(err) 395 } 396 req := &testpb.StreamingOutputCallRequest{ 397 ResponseType: testpb.PayloadType_COMPRESSABLE, 398 ResponseParameters: respParam, 399 Payload: payload, 400 } 401 // The existing RPC should be still good to proceed. 402 if err := stream.Send(req); err != nil { 403 t.Fatalf("%v.Send(%v) = %v, want <nil>", stream, req, err) 404 } 405 if _, err := stream.Recv(); err != nil { 406 t.Fatalf("%v.Recv() = _, %v, want _, <nil>", stream, err) 407 } 408 if err := stream.CloseSend(); err != nil { 409 t.Fatalf("%v.CloseSend() = %v, want <nil>", stream, err) 410 } 411 412 <-ch1 413 <-ch2 414 cancel() 415 awaitNewConnLogOutput() 416 } 417 418 func (s) TestConcurrentClientConnCloseAndServerGoAway(t *testing.T) { 419 for _, e := range listTestEnv() { 420 if e.name == "handler-tls" { 421 continue 422 } 423 testConcurrentClientConnCloseAndServerGoAway(t, e) 424 } 425 } 426 427 func testConcurrentClientConnCloseAndServerGoAway(t *testing.T, e env) { 428 te := newTest(t, e) 429 te.userAgent = testAppUA 430 te.declareLogNoise( 431 "transport: http2Client.notifyError got notified that the client transport was broken EOF", 432 "grpc: addrConn.transportMonitor exits due to: grpc: the connection is closing", 433 "grpc: addrConn.resetTransport failed to create client transport: connection error", 434 ) 435 te.startServer(&testServer{security: e.security}) 436 defer te.tearDown() 437 438 cc := te.clientConn() 439 tc := testgrpc.NewTestServiceClient(cc) 440 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 441 defer cancel() 442 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 443 t.Fatalf("%v.EmptyCall(_, _, _) = _, %v, want _, <nil>", tc, err) 444 } 445 ch := make(chan struct{}) 446 // Close ClientConn and Server concurrently. 447 go func() { 448 te.srv.GracefulStop() 449 close(ch) 450 }() 451 go func() { 452 cc.Close() 453 }() 454 <-ch 455 } 456 457 func (s) TestConcurrentServerStopAndGoAway(t *testing.T) { 458 for _, e := range listTestEnv() { 459 if e.name == "handler-tls" { 460 continue 461 } 462 testConcurrentServerStopAndGoAway(t, e) 463 } 464 } 465 466 func testConcurrentServerStopAndGoAway(t *testing.T, e env) { 467 te := newTest(t, e) 468 te.userAgent = testAppUA 469 te.declareLogNoise( 470 "transport: http2Client.notifyError got notified that the client transport was broken EOF", 471 "grpc: addrConn.transportMonitor exits due to: grpc: the connection is closing", 472 "grpc: addrConn.resetTransport failed to create client transport: connection error", 473 ) 474 te.startServer(&testServer{security: e.security}) 475 defer te.tearDown() 476 477 cc := te.clientConn() 478 tc := testgrpc.NewTestServiceClient(cc) 479 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 480 defer cancel() 481 stream, err := tc.FullDuplexCall(ctx, grpc.WaitForReady(true)) 482 if err != nil { 483 t.Fatalf("%v.FullDuplexCall(_) = _, %v, want <nil>", tc, err) 484 } 485 486 // Finish an RPC to make sure the connection is good. 487 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 488 t.Fatalf("%v.EmptyCall(_, _, _) = _, %v, want _, <nil>", tc, err) 489 } 490 491 ch := make(chan struct{}) 492 go func() { 493 te.srv.GracefulStop() 494 close(ch) 495 }() 496 // Loop until the server side GoAway signal is propagated to the client. 497 for { 498 ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 499 if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 500 cancel() 501 break 502 } 503 cancel() 504 } 505 // Stop the server and close all the connections. 506 te.srv.Stop() 507 respParam := []*testpb.ResponseParameters{ 508 { 509 Size: 1, 510 }, 511 } 512 payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(100)) 513 if err != nil { 514 t.Fatal(err) 515 } 516 req := &testpb.StreamingOutputCallRequest{ 517 ResponseType: testpb.PayloadType_COMPRESSABLE, 518 ResponseParameters: respParam, 519 Payload: payload, 520 } 521 sendStart := time.Now() 522 for { 523 if err := stream.Send(req); err == io.EOF { 524 // stream.Send should eventually send io.EOF 525 break 526 } else if err != nil { 527 // Send should never return a transport-level error. 528 t.Fatalf("stream.Send(%v) = %v; want <nil or io.EOF>", req, err) 529 } 530 if time.Since(sendStart) > 2*time.Second { 531 t.Fatalf("stream.Send(_) did not return io.EOF after 2s") 532 } 533 time.Sleep(time.Millisecond) 534 } 535 if _, err := stream.Recv(); err == nil || err == io.EOF { 536 t.Fatalf("%v.Recv() = _, %v, want _, <non-nil, non-EOF>", stream, err) 537 } 538 <-ch 539 awaitNewConnLogOutput() 540 } 541 542 // Proxies typically send GO_AWAY followed by connection closure a minute or so later. This 543 // test ensures that the connection is re-created after GO_AWAY and not affected by the 544 // subsequent (old) connection closure. 545 func (s) TestGoAwayThenClose(t *testing.T) { 546 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 547 defer cancel() 548 549 lis1, err := net.Listen("tcp", "localhost:0") 550 if err != nil { 551 t.Fatalf("Error while listening. Err: %v", err) 552 } 553 s1 := grpc.NewServer() 554 defer s1.Stop() 555 ts := &funcServer{ 556 unaryCall: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 557 return &testpb.SimpleResponse{}, nil 558 }, 559 fullDuplexCall: func(stream testgrpc.TestService_FullDuplexCallServer) error { 560 if err := stream.Send(&testpb.StreamingOutputCallResponse{}); err != nil { 561 t.Errorf("unexpected error from send: %v", err) 562 return err 563 } 564 // Wait forever. 565 _, err := stream.Recv() 566 if err == nil { 567 t.Error("expected to never receive any message") 568 } 569 return err 570 }, 571 } 572 testgrpc.RegisterTestServiceServer(s1, ts) 573 go s1.Serve(lis1) 574 575 conn2Established := grpcsync.NewEvent() 576 lis2, err := listenWithNotifyingListener("tcp", "localhost:0", conn2Established) 577 if err != nil { 578 t.Fatalf("Error while listening. Err: %v", err) 579 } 580 s2 := grpc.NewServer() 581 defer s2.Stop() 582 testgrpc.RegisterTestServiceServer(s2, ts) 583 584 r := manual.NewBuilderWithScheme("whatever") 585 r.InitialState(resolver.State{Addresses: []resolver.Address{ 586 {Addr: lis1.Addr().String()}, 587 {Addr: lis2.Addr().String()}, 588 }}) 589 cc, err := grpc.DialContext(ctx, r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 590 if err != nil { 591 t.Fatalf("Error creating client: %v", err) 592 } 593 defer cc.Close() 594 595 client := testgrpc.NewTestServiceClient(cc) 596 597 t.Log("Waiting for the ClientConn to enter READY state.") 598 testutils.AwaitState(ctx, t, cc, connectivity.Ready) 599 600 // We make a streaming RPC and do an one-message-round-trip to make sure 601 // it's created on connection 1. 602 // 603 // We use a long-lived RPC because it will cause GracefulStop to send 604 // GO_AWAY, but the connection won't get closed until the server stops and 605 // the client receives the error. 606 t.Log("Creating first streaming RPC to server 1.") 607 stream, err := client.FullDuplexCall(ctx) 608 if err != nil { 609 t.Fatalf("FullDuplexCall(_) = _, %v; want _, nil", err) 610 } 611 if _, err = stream.Recv(); err != nil { 612 t.Fatalf("unexpected error from first recv: %v", err) 613 } 614 615 go s2.Serve(lis2) 616 617 t.Log("Gracefully stopping server 1.") 618 go s1.GracefulStop() 619 620 t.Log("Waiting for the ClientConn to enter IDLE state.") 621 testutils.AwaitState(ctx, t, cc, connectivity.Idle) 622 623 t.Log("Performing another RPC to create a connection to server 2.") 624 if _, err := client.UnaryCall(ctx, &testpb.SimpleRequest{}); err != nil { 625 t.Fatalf("UnaryCall(_) = _, %v; want _, nil", err) 626 } 627 628 t.Log("Waiting for a connection to server 2.") 629 select { 630 case <-conn2Established.Done(): 631 case <-ctx.Done(): 632 t.Fatalf("timed out waiting for connection 2 to be established") 633 } 634 635 // Close the listener for server2 to prevent it from allowing new connections. 636 lis2.Close() 637 638 t.Log("Hard closing connection 1.") 639 s1.Stop() 640 641 t.Log("Waiting for the first stream to error.") 642 if _, err = stream.Recv(); err == nil { 643 t.Fatal("expected the stream to die, but got a successful Recv") 644 } 645 646 t.Log("Ensuring connection 2 is stable.") 647 for i := 0; i < 10; i++ { 648 if _, err := client.UnaryCall(ctx, &testpb.SimpleRequest{}); err != nil { 649 t.Fatalf("UnaryCall(_) = _, %v; want _, nil", err) 650 } 651 } 652 } 653 654 // TestGoAwayStreamIDSmallerThanCreatedStreams tests the scenario where a server 655 // sends a goaway with a stream id that is smaller than some created streams on 656 // the client, while the client is simultaneously creating new streams. This 657 // should not induce a deadlock. 658 func (s) TestGoAwayStreamIDSmallerThanCreatedStreams(t *testing.T) { 659 lis, err := net.Listen("tcp", "localhost:0") 660 if err != nil { 661 t.Fatalf("error listening: %v", err) 662 } 663 664 ctCh := testutils.NewChannel() 665 go func() { 666 conn, err := lis.Accept() 667 if err != nil { 668 t.Errorf("error in lis.Accept(): %v", err) 669 } 670 ct := newClientTester(t, conn) 671 ctCh.Send(ct) 672 }() 673 674 cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) 675 if err != nil { 676 t.Fatalf("error dialing: %v", err) 677 } 678 defer cc.Close() 679 680 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 681 defer cancel() 682 683 val, err := ctCh.Receive(ctx) 684 if err != nil { 685 t.Fatalf("timeout waiting for client transport (should be given after http2 creation)") 686 } 687 ct := val.(*clientTester) 688 689 tc := testgrpc.NewTestServiceClient(cc) 690 someStreamsCreated := grpcsync.NewEvent() 691 goAwayWritten := grpcsync.NewEvent() 692 go func() { 693 for i := 0; i < 20; i++ { 694 if i == 10 { 695 <-goAwayWritten.Done() 696 } 697 tc.FullDuplexCall(ctx) 698 if i == 4 { 699 someStreamsCreated.Fire() 700 } 701 } 702 }() 703 704 <-someStreamsCreated.Done() 705 ct.writeGoAway(1, http2.ErrCodeNo, []byte{}) 706 goAwayWritten.Fire() 707 } 708 709 // TestTwoGoAwayPingFrames tests the scenario where you get two go away ping 710 // frames from the client during graceful shutdown. This should not crash the 711 // server. 712 func (s) TestTwoGoAwayPingFrames(t *testing.T) { 713 lis, err := net.Listen("tcp", "localhost:0") 714 if err != nil { 715 t.Fatalf("Failed to listen: %v", err) 716 } 717 defer lis.Close() 718 s := grpc.NewServer() 719 defer s.Stop() 720 go s.Serve(lis) 721 722 conn, err := net.DialTimeout("tcp", lis.Addr().String(), defaultTestTimeout) 723 if err != nil { 724 t.Fatalf("Failed to dial: %v", err) 725 } 726 727 st := newServerTesterFromConn(t, conn) 728 st.greet() 729 pingReceivedClientSide := testutils.NewChannel() 730 go func() { 731 for { 732 f, err := st.readFrame() 733 if err != nil { 734 return 735 } 736 switch f.(type) { 737 case *http2.GoAwayFrame: 738 case *http2.PingFrame: 739 pingReceivedClientSide.Send(nil) 740 default: 741 t.Errorf("server tester received unexpected frame type %T", f) 742 } 743 } 744 }() 745 gsDone := testutils.NewChannel() 746 go func() { 747 s.GracefulStop() 748 gsDone.Send(nil) 749 }() 750 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 751 defer cancel() 752 if _, err := pingReceivedClientSide.Receive(ctx); err != nil { 753 t.Fatalf("Error waiting for ping frame client side from graceful shutdown: %v", err) 754 } 755 // Write two goaway pings here. 756 st.writePing(true, [8]byte{1, 6, 1, 8, 0, 3, 3, 9}) 757 st.writePing(true, [8]byte{1, 6, 1, 8, 0, 3, 3, 9}) 758 // Close the conn to finish up the Graceful Shutdown process. 759 conn.Close() 760 if _, err := gsDone.Receive(ctx); err != nil { 761 t.Fatalf("Error waiting for graceful shutdown of the server: %v", err) 762 } 763 }