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

Code before:
	stream, err := cc.NewStream(ctx, desc, "/grpc.testing.TestService/StreamingOutputCall")
	if err != nil {
		t.Fatalf("cc.NewStream() failed unexpectedly: %v", err)
	}

	if err := stream.SendMsg(&testpb.Empty{}); err != nil {
		t.Errorf("stream.SendMsg() = %v, want <nil>", err)
	}
	<-recvDoneOnServer
	if err := stream.SendMsg(&testpb.Empty{}); status.Code(err) != codes.Internal {
		t.Errorf("stream.SendMsg() = %v, want error %v", err, codes.Internal)
	}
	<-handlerDone
}

// Tests the behavior for unary RPC when client calls SendMsg twice. Second call
// to SendMsg should fail with Internal error.
func (s) TestUnaryRPC_ClientCallSendMsgTwice(t *testing.T) {
	ss := stubserver.StubServer{
		UnaryCallF: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
			return &testpb.SimpleResponse{}, nil
		},
	}
	if err := ss.Start(nil); err != nil {
		t.Fatal("Error starting server:", err)
	}
	defer ss.Stop()

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

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

	stream, err := cc.NewStream(ctx, desc, "/grpc.testing.TestService/UnaryCall")
	if err != nil {
		t.Fatalf("cc.NewStream() failed unexpectedly: %v", err)
	}

	if err := stream.SendMsg(&testpb.Empty{}); err != nil {
		t.Errorf("stream.SendMsg() = %v, want <nil>", err)
	}


Review comment (suggestion):
This is testing client-side checks.  We should also have an equivalent test for server-side checks of the same condition (which does not exist).  We do have tests for logic on the server for server-streaming RPCs, but not for unary.  Unary handling goes through a different code path.

We can add that as a follow-on PR.

Code after:
	desc := &grpc.StreamDesc{
		StreamName:    "StreamingOutputCall",
		ServerStreams: true,
		ClientStreams: false,
	}

	stream, err := cc.NewStream(ctx, desc, "/grpc.testing.TestService/StreamingOutputCall")
	if err != nil {
		t.Fatalf("cc.NewStream() failed unexpectedly: %v", err)
	}

	if err := stream.SendMsg(&testpb.Empty{}); err != nil {
		t.Errorf("stream.SendMsg() = %v, want <nil>", err)
	}

	<-recvDoneOnServer
	if err := stream.SendMsg(&testpb.Empty{}); status.Code(err) != codes.Internal {
		t.Errorf("stream.SendMsg() = %v, want error %v", err, codes.Internal)
	}
	<-handlerDone
}

// TODO(i/7286) : Add tests to check server-side behavior for Unary RPC.
// Tests the behavior for unary RPC when client calls SendMsg twice. Second call
// to SendMsg should fail with Internal error.
func (s) TestUnaryRPC_ClientCallSendMsgTwice(t *testing.T) {
	ss := stubserver.StubServer{
		UnaryCallF: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
			return &testpb.SimpleResponse{}, nil
		},
	}
	if err := ss.Start(nil); err != nil {
		t.Fatal("Error starting server:", err)
	}
	defer ss.Stop()

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

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

	stream, err := cc.NewStream(ctx, desc, "/grpc.testing.TestService/UnaryCall")