Tests that the client transport drains and restarts when next stream ID exceeds MaxStreamID. This test also verifies that subsequent RPCs use a new client transport and the old transport is closed.
(t *testing.T)
| 83 | // MaxStreamID. This test also verifies that subsequent RPCs use a new client |
| 84 | // transport and the old transport is closed. |
| 85 | func (s) TestClientTransportRestartsAfterStreamIDExhausted(t *testing.T) { |
| 86 | // Set the transport's MaxStreamID to 4 to cause connection to drain after 2 RPCs. |
| 87 | originalMaxStreamID := transport.MaxStreamID |
| 88 | transport.MaxStreamID = 4 |
| 89 | defer func() { |
| 90 | transport.MaxStreamID = originalMaxStreamID |
| 91 | }() |
| 92 | |
| 93 | ss := &stubserver.StubServer{ |
| 94 | FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { |
| 95 | if _, err := stream.Recv(); err != nil { |
| 96 | return status.Errorf(codes.Internal, "unexpected error receiving: %v", err) |
| 97 | } |
| 98 | if err := stream.Send(&testpb.StreamingOutputCallResponse{}); err != nil { |
| 99 | return status.Errorf(codes.Internal, "unexpected error sending: %v", err) |
| 100 | } |
| 101 | if recv, err := stream.Recv(); err != io.EOF { |
| 102 | return status.Errorf(codes.Internal, "Recv = %v, %v; want _, io.EOF", recv, err) |
| 103 | } |
| 104 | return nil |
| 105 | }, |
| 106 | } |
| 107 | |
| 108 | creds := &transportRestartCheckCreds{} |
| 109 | if err := ss.Start(nil, grpc.WithTransportCredentials(creds)); err != nil { |
| 110 | t.Fatalf("Starting stubServer: %v", err) |
| 111 | } |
| 112 | defer ss.Stop() |
| 113 | |
| 114 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 115 | defer cancel() |
| 116 | |
| 117 | var streams []testgrpc.TestService_FullDuplexCallClient |
| 118 | |
| 119 | const numStreams = 3 |
| 120 | // expected number of conns when each stream is created i.e., 3rd stream is created |
| 121 | // on a new connection. |
| 122 | expectedNumConns := [numStreams]int{1, 1, 2} |
| 123 | |
| 124 | // Set up 3 streams. |
| 125 | for i := 0; i < numStreams; i++ { |
| 126 | s, err := ss.Client.FullDuplexCall(ctx) |
| 127 | if err != nil { |
| 128 | t.Fatalf("Creating FullDuplex stream: %v", err) |
| 129 | } |
| 130 | streams = append(streams, s) |
| 131 | // Verify expected num of conns after each stream is created. |
| 132 | if len(creds.connections) != expectedNumConns[i] { |
| 133 | t.Fatalf("Got number of connections created: %v, want: %v", len(creds.connections), expectedNumConns[i]) |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | // Verify all streams still work. |
| 138 | for i, stream := range streams { |
| 139 | if err := stream.Send(&testpb.StreamingOutputCallRequest{}); err != nil { |
| 140 | t.Fatalf("Sending on stream %d: %v", i, err) |
| 141 | } |
| 142 | if _, err := stream.Recv(); err != nil { |
nothing calls this directly
no test coverage detected