Repository: grpc/grpc-go
File: test/end2end_test.go (Go)

Code before:

// Tests that a client receives a cardinality violation error for unary
// RPCs if the server doesn't send a message before returning status OK.
func (s) TestUnaryRPC_ServerSendsOnlyTrailersWithOK(t *testing.T) {
	lis, err := testutils.LocalTCPListener()
	if err != nil {
		t.Fatal(err)
	}
	defer lis.Close()

	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()
	cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("grpc.NewClient(%s) = %v", lis.Addr().String(), err)
	}
	defer cc.Close()

	go func() {
		conn, err := lis.Accept()
		if err != nil {
			t.Errorf("lis.Accept() = %v", err)
			return
		}
		defer conn.Close()
		framer := http2.NewFramer(conn, conn)

		if _, err := io.ReadFull(conn, make([]byte, len(clientPreface))); err != nil {
			t.Errorf("Error reading client preface: %v", err)
			return
		}
		if err := framer.WriteSettings(); err != nil {
			t.Errorf("Error writing server settings: %v", err)
			return
		}
		if err := framer.WriteSettingsAck(); err != nil {
			t.Errorf("Error writing settings ack: %v", err)
			return
		}

		for ctx.Err() == nil {
			frame, err := framer.ReadFrame()
			if err != nil {
				t.Errorf("Error reading frame: %v", err)
				return
			}

			switch frame := frame.(type) {
			case *http2.HeadersFrame:
				if frame.Header().StreamID != 1 {
					t.Errorf("Expected stream ID 1, got %d", frame.Header().StreamID)

Review comment (suggestion):
Realistically this test shouldn't need low level framer access.  You should be able to implement it with a `grpc.Server` that has its `EmptyCall` handler configured as a streaming handling, and with an implementation that just returns `nil` immediately without sending a message.

I do think that would be preferable, because the framing stuff is tedious and error prone, and it makes the test much more complex.  If you're having too much trouble with that approach, let me know and I can try to help, or if it somehow turns out to be a lot more work than I was expecting, feel free to push back.

Code after:
}

// Tests that a client receives a cardinality violation error for unary
// RPCs if the server doesn't send a message before returning status OK.
func (s) TestUnaryRPC_ServerSendsOnlyTrailersWithOK(t *testing.T) {
	lis, err := testutils.LocalTCPListener()
	if err != nil {
		t.Fatal(err)
	}
	defer lis.Close()

	ss := grpc.UnknownServiceHandler(func(any, grpc.ServerStream) error {
		return nil
	})

	s := grpc.NewServer(ss)
	go s.Serve(lis)
	defer s.Stop()

	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()
	cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("grpc.NewClient(%q) failed unexpectedly: %v", lis.Addr(), err)
	}
	defer cc.Close()

	client := testgrpc.NewTestServiceClient(cc)
	if _, err = client.EmptyCall(ctx, &testpb.Empty{}); status.Code(err) != codes.Internal {
		t.Errorf("stream.RecvMsg() = %v, want error %v", status.Code(err), codes.Internal)
	}
}

// Tests that client will receive cardinality violations when calling
// RecvMsg() multiple times for non-streaming response streams.
func (s) TestUnaryRPC_ClientCallRecvMsgTwice(t *testing.T) {
	e := tcpTLSEnv
	te := newTest(t, e)
	defer te.tearDown()

	te.startServer(&testServer{security: e.security})

	cc := te.clientConn()
	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()

	desc := &grpc.StreamDesc{
		StreamName:    "UnaryCall",
		ServerStreams: false,
		ClientStreams: false,
	}