diff --git a/internal/transport/transport_test.go b/internal/transport/transport_test.go index f31eda6d2985..6fa9391f498b 100644 --- a/internal/transport/transport_test.go +++ b/internal/transport/transport_test.go @@ -2593,19 +2593,21 @@ func TestConnectionError_Unwrap(t *testing.T) { } } -func TestServerOperateHeaderOnEvenStreamID(t *testing.T) { +// Test gRPC server's operateHeaders on a header with even stream ID. +// Per [HTTP/2 spec]: Streams initiated by a client MUST use +// odd-numbered stream identifiers. When received even stream ID, the +// operateHeader returns error instead of writing the frame to the transport. +// +// [HTTP/2 spec]: https://httpwg.org/specs/rfc7540.html#StreamIdentifiers +func TestServerOperateHeaderFailOnEvenStreamID(t *testing.T) { hf := &http2.HeadersFrame{FrameHeader: http2.FrameHeader{StreamID: 2}} metaHeaderFrame := &http2.MetaHeadersFrame{HeadersFrame: hf} s := http2Server{} ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() err := s.operateHeaders(ctx, metaHeaderFrame, nil) - if err == nil { - t.Fatalf("Error expected on the even stream ID. got %v", err) - } - possibleErrMsg := "received an illegal stream id: 2" - if !strings.Contains(err.Error(), possibleErrMsg) { - t.Fatalf("Expected partial error message: %v, got %v", possibleErrMsg, err.Error()) + want := "received an illegal stream id: 2" + if got := err.Error(); got != want { + t.Fatalf("http2Server.operateHeaders() returned err: %v; want: %v", got, want) } - defer cancel() - } diff --git a/test/end2end_test.go b/test/end2end_test.go index 295f06bf2b80..8b34f735bd70 100644 --- a/test/end2end_test.go +++ b/test/end2end_test.go @@ -3909,17 +3909,26 @@ func (s) TestClientRequestBodyErrorCloseAfterLength(t *testing.T) { // // [HTTP/2 spec]: https://httpwg.org/specs/rfc7540.html#StreamIdentifiers func (s) TestClientInvalidStreamID(t *testing.T) { - te := newTest(t, tcpClearEnv) - te.startServer(nil) - defer te.tearDown() - serverTesterFunc := func(st *serverTester) { - st.writeHeadersGRPC(2, "/grpc.testing.TestService/StreamingInputCall", true) - _, err := st.fr.ReadFrame() - if err != io.EOF { - t.Fatalf("Error expected when Client StreamID is even %v", err) - } + lis, err := net.Listen("tcp", "localhost:0") + if err != nil { + t.Fatalf("Failed to listen: %v", err) + } + defer lis.Close() + s := grpc.NewServer() + defer s.Stop() + go s.Serve(lis) + + conn, err := net.DialTimeout("tcp", lis.Addr().String(), defaultTestTimeout) + if err != nil { + t.Fatalf("Failed to dial: %v", err) + } + st := newServerTesterFromConn(t, conn) + st.greet() + st.writeHeadersGRPC(2, "/grpc.testing.TestService/StreamingInputCall", true) + _, err = st.fr.ReadFrame() + if err != io.EOF { + t.Fatalf("Error expected when Client StreamID is even %v", err) } - te.withServerTester(serverTesterFunc) } func testClientRequestBodyErrorCloseAfterLength(t *testing.T, e env) {