Add unary call mode to GenericStub to allow generic RPC with 1 CQ trip

pull/12645/head
Vijay Pai 7 years ago
parent 87973ea398
commit 2046d0b3c5
  1. 10
      include/grpc++/generic/generic_stub.h
  2. 10
      src/cpp/client/generic_stub.cc
  3. 56
      test/cpp/end2end/generic_end2end_test.cc

@ -20,6 +20,7 @@
#define GRPCXX_GENERIC_GENERIC_STUB_H
#include <grpc++/support/async_stream.h>
#include <grpc++/support/async_unary_call.h>
#include <grpc++/support/byte_buffer.h>
namespace grpc {
@ -27,6 +28,7 @@ namespace grpc {
class CompletionQueue;
typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
GenericClientAsyncReaderWriter;
typedef ClientAsyncResponseReader<ByteBuffer> GenericClientAsyncResponseReader;
/// Generic stubs provide a type-unsafe interface to call gRPC methods
/// by name.
@ -51,6 +53,14 @@ class GenericStub final {
std::unique_ptr<GenericClientAsyncReaderWriter> PrepareCall(
ClientContext* context, const grpc::string& method, CompletionQueue* cq);
/// Setup a unary call to a named method \a method using \a context, and don't
/// start it. Let it be started explicitly with StartCall.
/// The return value only indicates whether or not registration of the call
/// succeeded (i.e. the call won't proceed if the return value is nullptr).
std::unique_ptr<GenericClientAsyncResponseReader> PrepareUnaryCall(
ClientContext* context, const grpc::string& method,
const ByteBuffer& request, CompletionQueue* cq);
private:
std::shared_ptr<ChannelInterface> channel_;
};

@ -47,4 +47,14 @@ std::unique_ptr<GenericClientAsyncReaderWriter> GenericStub::PrepareCall(
return CallInternal(channel_.get(), context, method, cq, false, nullptr);
}
// setup a unary call to a named method
std::unique_ptr<GenericClientAsyncResponseReader> GenericStub::PrepareUnaryCall(
ClientContext* context, const grpc::string& method,
const ByteBuffer& request, CompletionQueue* cq) {
return std::unique_ptr<GenericClientAsyncResponseReader>(
GenericClientAsyncResponseReader::Create(
channel_.get(), cq, RpcMethod(method.c_str(), RpcMethod::NORMAL_RPC),
context, request, false));
}
} // namespace grpc

@ -196,6 +196,62 @@ TEST_F(GenericEnd2endTest, SequentialRpcs) {
SendRpc(10);
}
TEST_F(GenericEnd2endTest, SequentialUnaryRpcs) {
ResetStub();
const int num_rpcs = 10;
const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo");
for (int i = 0; i < num_rpcs; i++) {
EchoRequest send_request;
EchoRequest recv_request;
EchoResponse send_response;
EchoResponse recv_response;
Status recv_status;
ClientContext cli_ctx;
GenericServerContext srv_ctx;
GenericServerAsyncReaderWriter stream(&srv_ctx);
// The string needs to be long enough to test heap-based slice.
send_request.set_message("Hello world. Hello world. Hello world.");
std::unique_ptr<ByteBuffer> cli_send_buffer =
SerializeToByteBuffer(&send_request);
std::unique_ptr<GenericClientAsyncResponseReader> call =
generic_stub_->PrepareUnaryCall(&cli_ctx, kMethodName,
*cli_send_buffer.get(), &cli_cq_);
call->StartCall();
ByteBuffer cli_recv_buffer;
call->Finish(&cli_recv_buffer, &recv_status, tag(1));
generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(),
srv_cq_.get(), tag(4));
verify_ok(srv_cq_.get(), 4, true);
EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length()));
EXPECT_EQ(kMethodName, srv_ctx.method());
ByteBuffer srv_recv_buffer;
stream.Read(&srv_recv_buffer, tag(5));
server_ok(5);
EXPECT_TRUE(ParseFromByteBuffer(&srv_recv_buffer, &recv_request));
EXPECT_EQ(send_request.message(), recv_request.message());
send_response.set_message(recv_request.message());
std::unique_ptr<ByteBuffer> srv_send_buffer =
SerializeToByteBuffer(&send_response);
stream.Write(*srv_send_buffer, tag(6));
server_ok(6);
stream.Finish(Status::OK, tag(7));
server_ok(7);
client_ok(1);
EXPECT_TRUE(ParseFromByteBuffer(&cli_recv_buffer, &recv_response));
EXPECT_EQ(send_response.message(), recv_response.message());
EXPECT_TRUE(recv_status.ok());
}
}
// One ping, one pong.
TEST_F(GenericEnd2endTest, SimpleBidiStreaming) {
ResetStub();

Loading…
Cancel
Save