aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Vijay Pai <vpai@google.com>2017-09-22 11:08:59 -0700
committerGravatar GitHub <noreply@github.com>2017-09-22 11:08:59 -0700
commitaa9779184c86d0fd9167d62bc7e832c45cb14d01 (patch)
tree9503fa8c0e57f7f9581c5eaa0082fc741ecadd53
parent6ac3f996804f4325217b13f9407b2f0a283ba5aa (diff)
parent2046d0b3c50e555f339062b4fba298e8af8b3a1f (diff)
Merge pull request #12645 from vjpai/generic_unary
C++ GenericStub: add unary call mode
-rw-r--r--include/grpc++/generic/generic_stub.h10
-rw-r--r--src/cpp/client/generic_stub.cc10
-rw-r--r--test/cpp/end2end/generic_end2end_test.cc56
3 files changed, 76 insertions, 0 deletions
diff --git a/include/grpc++/generic/generic_stub.h b/include/grpc++/generic/generic_stub.h
index 2b3ff59ea2..d5064318cf 100644
--- a/include/grpc++/generic/generic_stub.h
+++ b/include/grpc++/generic/generic_stub.h
@@ -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_;
};
diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc
index de2e449fe8..693b8bea56 100644
--- a/src/cpp/client/generic_stub.cc
+++ b/src/cpp/client/generic_stub.cc
@@ -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
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index b9e6e18ca7..33b35108d2 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -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();