google.golang.org/grpc@v1.62.1/interop/http2/negative_http2_client.go (about) 1 /* 2 * 3 * Copyright 2016 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 // Binary http2 is used to test http2 error edge cases like GOAWAYs and 20 // RST_STREAMs 21 // 22 // Documentation: 23 // https://github.com/grpc/grpc/blob/master/doc/negative-http2-interop-test-descriptions.md 24 package main 25 26 import ( 27 "context" 28 "flag" 29 "net" 30 "strconv" 31 "sync" 32 "time" 33 34 "google.golang.org/grpc" 35 "google.golang.org/grpc/codes" 36 "google.golang.org/grpc/credentials/insecure" 37 "google.golang.org/grpc/grpclog" 38 "google.golang.org/grpc/interop" 39 "google.golang.org/grpc/status" 40 41 testgrpc "google.golang.org/grpc/interop/grpc_testing" 42 testpb "google.golang.org/grpc/interop/grpc_testing" 43 ) 44 45 var ( 46 serverHost = flag.String("server_host", "localhost", "The server host name") 47 serverPort = flag.Int("server_port", 8080, "The server port number") 48 testCase = flag.String("test_case", "goaway", 49 `Configure different test cases. Valid options are: 50 goaway : client sends two requests, the server will send a goaway in between; 51 rst_after_header : server will send rst_stream after it sends headers; 52 rst_during_data : server will send rst_stream while sending data; 53 rst_after_data : server will send rst_stream after sending data; 54 ping : server will send pings between each http2 frame; 55 max_streams : server will ensure that the max_concurrent_streams limit is upheld;`) 56 largeReqSize = 271828 57 largeRespSize = 314159 58 59 logger = grpclog.Component("interop") 60 ) 61 62 func largeSimpleRequest() *testpb.SimpleRequest { 63 pl := interop.ClientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize) 64 return &testpb.SimpleRequest{ 65 ResponseType: testpb.PayloadType_COMPRESSABLE, 66 ResponseSize: int32(largeRespSize), 67 Payload: pl, 68 } 69 } 70 71 // sends two unary calls. The server asserts that the calls use different connections. 72 func goaway(ctx context.Context, tc testgrpc.TestServiceClient) { 73 interop.DoLargeUnaryCall(ctx, tc) 74 // sleep to ensure that the client has time to recv the GOAWAY. 75 // TODO(ncteisen): make this less hacky. 76 time.Sleep(1 * time.Second) 77 interop.DoLargeUnaryCall(ctx, tc) 78 } 79 80 func rstAfterHeader(tc testgrpc.TestServiceClient) { 81 req := largeSimpleRequest() 82 reply, err := tc.UnaryCall(context.Background(), req) 83 if reply != nil { 84 logger.Fatal("Client received reply despite server sending rst stream after header") 85 } 86 if status.Code(err) != codes.Internal { 87 logger.Fatalf("%v.UnaryCall() = _, %v, want _, %v", tc, status.Code(err), codes.Internal) 88 } 89 } 90 91 func rstDuringData(tc testgrpc.TestServiceClient) { 92 req := largeSimpleRequest() 93 reply, err := tc.UnaryCall(context.Background(), req) 94 if reply != nil { 95 logger.Fatal("Client received reply despite server sending rst stream during data") 96 } 97 if status.Code(err) != codes.Unknown { 98 logger.Fatalf("%v.UnaryCall() = _, %v, want _, %v", tc, status.Code(err), codes.Unknown) 99 } 100 } 101 102 func rstAfterData(tc testgrpc.TestServiceClient) { 103 req := largeSimpleRequest() 104 reply, err := tc.UnaryCall(context.Background(), req) 105 if reply != nil { 106 logger.Fatal("Client received reply despite server sending rst stream after data") 107 } 108 if status.Code(err) != codes.Internal { 109 logger.Fatalf("%v.UnaryCall() = _, %v, want _, %v", tc, status.Code(err), codes.Internal) 110 } 111 } 112 113 func ping(ctx context.Context, tc testgrpc.TestServiceClient) { 114 // The server will assert that every ping it sends was ACK-ed by the client. 115 interop.DoLargeUnaryCall(ctx, tc) 116 } 117 118 func maxStreams(ctx context.Context, tc testgrpc.TestServiceClient) { 119 interop.DoLargeUnaryCall(ctx, tc) 120 var wg sync.WaitGroup 121 for i := 0; i < 15; i++ { 122 wg.Add(1) 123 go func() { 124 defer wg.Done() 125 interop.DoLargeUnaryCall(ctx, tc) 126 }() 127 } 128 wg.Wait() 129 } 130 131 func main() { 132 flag.Parse() 133 serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort)) 134 var opts []grpc.DialOption 135 opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) 136 conn, err := grpc.Dial(serverAddr, opts...) 137 if err != nil { 138 logger.Fatalf("Fail to dial: %v", err) 139 } 140 defer conn.Close() 141 tc := testgrpc.NewTestServiceClient(conn) 142 ctx := context.Background() 143 switch *testCase { 144 case "goaway": 145 goaway(ctx, tc) 146 logger.Infoln("goaway done") 147 case "rst_after_header": 148 rstAfterHeader(tc) 149 logger.Infoln("rst_after_header done") 150 case "rst_during_data": 151 rstDuringData(tc) 152 logger.Infoln("rst_during_data done") 153 case "rst_after_data": 154 rstAfterData(tc) 155 logger.Infoln("rst_after_data done") 156 case "ping": 157 ping(ctx, tc) 158 logger.Infoln("ping done") 159 case "max_streams": 160 maxStreams(ctx, tc) 161 logger.Infoln("max_streams done") 162 default: 163 logger.Fatal("Unsupported test case: ", *testCase) 164 } 165 }