aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/cpp/util
diff options
context:
space:
mode:
authorGravatar Feso <gabor.fecher@gmail.com>2018-10-03 00:50:57 +0100
committerGravatar Feso <gabor.fecher@gmail.com>2018-10-03 00:50:57 +0100
commit44cecbb2f73d1aaf65fd67d2e413c891210f54f1 (patch)
treecc3cf0452b9a49e482303f6ae81c0c552fb8b857 /test/cpp/util
parent95dc4f1b8dfe30c7b983147690f483e0894687fd (diff)
grpc_cli json support
Diffstat (limited to 'test/cpp/util')
-rw-r--r--test/cpp/util/config_grpc_cli.h7
-rw-r--r--test/cpp/util/grpc_tool.cc103
-rw-r--r--test/cpp/util/grpc_tool_test.cc379
-rw-r--r--test/cpp/util/proto_file_parser.cc81
-rw-r--r--test/cpp/util/proto_file_parser.h20
5 files changed, 561 insertions, 29 deletions
diff --git a/test/cpp/util/config_grpc_cli.h b/test/cpp/util/config_grpc_cli.h
index 358884196d..1df7b36e2e 100644
--- a/test/cpp/util/config_grpc_cli.h
+++ b/test/cpp/util/config_grpc_cli.h
@@ -40,6 +40,11 @@
#define GRPC_CUSTOM_TEXTFORMAT ::google::protobuf::TextFormat
#endif
+#ifndef GRPC_CUSTOM_JSONUTIL
+#include <google/protobuf/util/json_util.h>
+#define GRPC_CUSTOM_JSONUTIL ::google::protobuf::util
+#endif
+
#ifndef GRPC_CUSTOM_DISKSOURCETREE
#include <google/protobuf/compiler/importer.h>
#define GRPC_CUSTOM_DISKSOURCETREE ::google::protobuf::compiler::DiskSourceTree
@@ -58,6 +63,8 @@ typedef GRPC_CUSTOM_MERGEDDESCRIPTORDATABASE MergedDescriptorDatabase;
typedef GRPC_CUSTOM_TEXTFORMAT TextFormat;
+namespace json = GRPC_CUSTOM_JSONUTIL;
+
namespace compiler {
typedef GRPC_CUSTOM_DISKSOURCETREE DiskSourceTree;
typedef GRPC_CUSTOM_IMPORTER Importer;
diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc
index ccc60cca27..b4eeee1a9b 100644
--- a/test/cpp/util/grpc_tool.cc
+++ b/test/cpp/util/grpc_tool.cc
@@ -57,6 +57,8 @@ DEFINE_string(proto_path, ".", "Path to look for the proto file.");
DEFINE_string(protofiles, "", "Name of the proto file.");
DEFINE_bool(binary_input, false, "Input in binary format");
DEFINE_bool(binary_output, false, "Output in binary format");
+DEFINE_bool(json_input, false, "Input in json format");
+DEFINE_bool(json_output, false, "Output in json format");
DEFINE_string(infile, "", "Input file (default is stdin)");
DEFINE_bool(batch, false,
"Input contains multiple requests. Please do not use this to send "
@@ -88,6 +90,8 @@ class GrpcTool {
GrpcToolOutputCallback callback);
bool ToText(int argc, const char** argv, const CliCredentials& cred,
GrpcToolOutputCallback callback);
+ bool ToJson(int argc, const char** argv, const CliCredentials& cred,
+ GrpcToolOutputCallback callback);
bool ToBinary(int argc, const char** argv, const CliCredentials& cred,
GrpcToolOutputCallback callback);
@@ -233,6 +237,7 @@ const Command ops[] = {
{"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3},
{"totext", BindWith5Args(&GrpcTool::ToText), 2, 3},
{"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3},
+ {"tojson", BindWith5Args(&GrpcTool::ToJson), 2, 3},
};
void Usage(const grpc::string& msg) {
@@ -244,6 +249,7 @@ void Usage(const grpc::string& msg) {
" grpc_cli type ... ; Print type\n"
" grpc_cli parse ... ; Parse message\n"
" grpc_cli totext ... ; Convert binary message to text\n"
+ " grpc_cli tojson ... ; Convert binary message to json\n"
" grpc_cli tobinary ... ; Convert text message to binary\n"
" grpc_cli help ... ; Print this message, or per-command usage\n"
"\n",
@@ -465,7 +471,9 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
" --infile ; Input filename (defaults to stdin)\n"
" --outfile ; Output filename (defaults to stdout)\n"
" --binary_input ; Input in binary format\n"
- " --binary_output ; Output in binary format\n" +
+ " --binary_output ; Output in binary format\n"
+ " --json_input ; Input in json format\n"
+ " --json_output ; Output in json format\n" +
cred.GetCredentialUsage());
std::stringstream output_ss;
@@ -547,8 +555,12 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
request_text.clear();
} else {
gpr_mu_lock(&parser_mu);
- serialized_request_proto = parser->GetSerializedProtoFromMethod(
- method_name, request_text, true /* is_request */);
+ serialized_request_proto =
+ FLAGS_json_input ?
+ parser->GetSerializedProtoFromMethodJsonFormat(
+ method_name, request_text, true /* is_request */) :
+ parser->GetSerializedProtoFromMethodTextFormat(
+ method_name, request_text, true /* is_request */);
request_text.clear();
if (parser->HasError()) {
if (print_mode) {
@@ -631,8 +643,12 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
serialized_request_proto = request_text;
request_text.clear();
} else {
- serialized_request_proto = parser->GetSerializedProtoFromMethod(
- method_name, request_text, true /* is_request */);
+ serialized_request_proto =
+ FLAGS_json_input ?
+ parser->GetSerializedProtoFromMethodJsonFormat(
+ method_name, request_text, true /* is_request */) :
+ parser->GetSerializedProtoFromMethodTextFormat(
+ method_name, request_text, true /* is_request */);
request_text.clear();
if (parser->HasError()) {
if (print_mode) {
@@ -668,9 +684,15 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
break;
}
} else {
- grpc::string response_text = parser->GetTextFormatFromMethod(
- method_name, serialized_response_proto,
- false /* is_request */);
+ grpc::string response_text =
+ FLAGS_json_output ?
+ parser->GetJsonFormatFromMethod(method_name,
+ serialized_response_proto,
+ false /* is_request */) :
+ parser->GetTextFormatFromMethod(method_name,
+ serialized_response_proto,
+ false /* is_request */);
+
if (parser->HasError() && print_mode) {
fprintf(stderr, "Failed to parse response.\n");
} else {
@@ -726,8 +748,12 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
if (FLAGS_binary_input) {
serialized_request_proto = request_text;
} else {
- serialized_request_proto = parser->GetSerializedProtoFromMethod(
- method_name, request_text, true /* is_request */);
+ serialized_request_proto =
+ FLAGS_json_input ?
+ parser->GetSerializedProtoFromMethodJsonFormat(
+ method_name, request_text, true /* is_request */) :
+ parser->GetSerializedProtoFromMethodTextFormat(
+ method_name, request_text, true /* is_request */);
if (parser->HasError()) {
fprintf(stderr, "Failed to parse request.\n");
return false;
@@ -750,14 +776,20 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
&serialized_response_proto,
receive_initial_metadata ? &server_initial_metadata : nullptr);
receive_initial_metadata = false) {
- if (!FLAGS_binary_output) {
+ if (FLAGS_json_output) {
+ serialized_response_proto = parser->GetJsonFormatFromMethod(
+ method_name, serialized_response_proto, false /* is_request */);
+ } else if (!FLAGS_binary_output) {
serialized_response_proto = parser->GetTextFormatFromMethod(
method_name, serialized_response_proto, false /* is_request */);
- if (parser->HasError()) {
- fprintf(stderr, "Failed to parse response.\n");
- return false;
- }
}
+ if (FLAGS_json_output || !FLAGS_binary_output) {
+ if (parser->HasError()) {
+ fprintf(stderr, "Failed to parse response.\n");
+ return false;
+ }
+ }
+
if (receive_initial_metadata) {
PrintMetadata(server_initial_metadata,
"Received initial metadata from server:");
@@ -797,7 +829,9 @@ bool GrpcTool::ParseMessage(int argc, const char** argv,
" --infile ; Input filename (defaults to stdin)\n"
" --outfile ; Output filename (defaults to stdout)\n"
" --binary_input ; Input in binary format\n"
- " --binary_output ; Output in binary format\n" +
+ " --binary_output ; Output in binary format\n"
+ " --json_input ; Input in json format\n"
+ " --json_output ; Output in json format\n" +
cred.GetCredentialUsage());
std::stringstream output_ss;
@@ -845,7 +879,11 @@ bool GrpcTool::ParseMessage(int argc, const char** argv,
serialized_request_proto = message_text;
} else {
serialized_request_proto =
- parser->GetSerializedProtoFromMessageType(type_name, message_text);
+ FLAGS_json_input ?
+ parser->GetSerializedProtoFromMessageTypeJsonFormat(type_name,
+ message_text) :
+ parser->GetSerializedProtoFromMessageTypeTextFormat(type_name,
+ message_text);
if (parser->HasError()) {
fprintf(stderr, "Failed to serialize the message.\n");
return false;
@@ -855,12 +893,20 @@ bool GrpcTool::ParseMessage(int argc, const char** argv,
if (FLAGS_binary_output) {
output_ss << serialized_request_proto;
} else {
- grpc::string output_text = parser->GetTextFormatFromMessageType(
- type_name, serialized_request_proto);
+ grpc::string output_text;
+ if (FLAGS_json_output) {
+ output_text = parser->GetJsonFormatFromMessageType(
+ type_name, serialized_request_proto);
+ } else {
+ output_text = parser->GetTextFormatFromMessageType(
+ type_name, serialized_request_proto);
+ }
+
if (parser->HasError()) {
fprintf(stderr, "Failed to deserialize the message.\n");
return false;
}
+
output_ss << output_text << std::endl;
}
@@ -885,6 +931,25 @@ bool GrpcTool::ToText(int argc, const char** argv, const CliCredentials& cred,
return ParseMessage(argc, argv, cred, callback);
}
+bool GrpcTool::ToJson(int argc, const char** argv, const CliCredentials& cred,
+ GrpcToolOutputCallback callback) {
+ CommandUsage(
+ "Convert binary message to json\n"
+ " grpc_cli tojson <protofiles> <type>\n"
+ " <protofiles> ; Comma separated list of proto files\n"
+ " <type> ; Protocol buffer type name\n"
+ " --proto_path ; The search path of proto files\n"
+ " --infile ; Input filename (defaults to stdin)\n"
+ " --outfile ; Output filename (defaults to stdout)\n");
+
+ FLAGS_protofiles = argv[0];
+ FLAGS_remotedb = false;
+ FLAGS_binary_input = true;
+ FLAGS_binary_output = false;
+ FLAGS_json_output = true;
+ return ParseMessage(argc, argv, cred, callback);
+}
+
bool GrpcTool::ToBinary(int argc, const char** argv, const CliCredentials& cred,
GrpcToolOutputCallback callback) {
CommandUsage(
diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc
index 3aae090e81..4409b5b7ed 100644
--- a/test/cpp/util/grpc_tool_test.cc
+++ b/test/cpp/util/grpc_tool_test.cc
@@ -74,13 +74,22 @@ using grpc::testing::EchoResponse;
" rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
"{}\n"
-#define ECHO_RESPONSE_MESSAGE \
+#define ECHO_RESPONSE_MESSAGE_TEXT_FORMAT \
"message: \"echo\"\n" \
"param {\n" \
" host: \"localhost\"\n" \
" peer: \"peer\"\n" \
"}\n\n"
+#define ECHO_RESPONSE_MESSAGE_JSON_FORMAT \
+ "{\n" \
+ " \"message\": \"echo\",\n" \
+ " \"param\": {\n" \
+ " \"host\": \"localhost\",\n" \
+ " \"peer\": \"peer\"\n" \
+ " }\n" \
+ "}\n\n"
+
DECLARE_string(channel_creds_type);
DECLARE_string(ssl_target);
@@ -89,6 +98,8 @@ namespace testing {
DECLARE_bool(binary_input);
DECLARE_bool(binary_output);
+DECLARE_bool(json_input);
+DECLARE_bool(json_output);
DECLARE_bool(l);
DECLARE_bool(batch);
DECLARE_string(metadata);
@@ -426,6 +437,61 @@ TEST_F(GrpcToolTest, CallCommand) {
// Expected output: "message: \"Hello\""
EXPECT_TRUE(nullptr !=
strstr(output_stream.str().c_str(), "message: \"Hello\""));
+
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+
+ FLAGS_json_output = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output = false;
+
+ // Expected output:
+ // {
+ // "message": "Hello"
+ // }
+ EXPECT_TRUE(nullptr !=
+ strstr(output_stream.str().c_str(), "{\n \"message\": \"Hello\"\n}"));
+
+ ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandJsonInput) {
+ // Test input "grpc_cli call localhost:<port> Echo "{ \"message\": \"Hello\"}"
+ std::stringstream output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
+ "{ \"message\": \"Hello\"}"};
+
+ FLAGS_json_input = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ // Expected output: "message: \"Hello\""
+ EXPECT_TRUE(nullptr !=
+ strstr(output_stream.str().c_str(), "message: \"Hello\""));
+
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+
+ FLAGS_json_output = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output = false;
+ FLAGS_json_input = false;
+
+ // Expected output:
+ // {
+ // "message": "Hello"
+ // }
+ EXPECT_TRUE(nullptr !=
+ strstr(output_stream.str().c_str(), "{\n \"message\": \"Hello\"\n}"));
+
ShutdownServer();
}
@@ -453,6 +519,101 @@ TEST_F(GrpcToolTest, CallCommandBatch) {
EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
"message: \"Hello0\"\nmessage: "
"\"Hello1\"\nmessage: \"Hello2\"\n"));
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+ ss.clear();
+ ss.seekg(0);
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_batch = true;
+ FLAGS_json_output= true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output= false;
+ FLAGS_batch = false;
+
+ // Expected output:
+ // {
+ // "message": "Hello0"
+ // }
+ // {
+ // "message": "Hello1"
+ // }
+ // {
+ // "message": "Hello2"
+ // }
+ // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
+ // "Hello2"\n"
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "{\n \"message\": \"Hello0\"\n}\n"
+ "{\n \"message\": \"Hello1\"\n}\n"
+ "{\n \"message\": \"Hello2\"\n}\n"));
+
+ std::cin.rdbuf(orig);
+ ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandBatchJsonInput) {
+ // Test input "grpc_cli call Echo"
+ std::stringstream output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
+ "{\"message\": \"Hello0\"}"};
+
+ // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
+ std::streambuf* orig = std::cin.rdbuf();
+ std::istringstream ss("{\"message\": \"Hello1\"}\n\n{\"message\": \"Hello2\" }\n\n");
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_json_input = true;
+ FLAGS_batch = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_batch = false;
+
+ // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
+ // "Hello2"\n"
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "message: \"Hello0\"\nmessage: "
+ "\"Hello1\"\nmessage: \"Hello2\"\n"));
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+ ss.clear();
+ ss.seekg(0);
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_batch = true;
+ FLAGS_json_output= true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output= false;
+ FLAGS_batch = false;
+ FLAGS_json_input = false;
+
+ // Expected output:
+ // {
+ // "message": "Hello0"
+ // }
+ // {
+ // "message": "Hello1"
+ // }
+ // {
+ // "message": "Hello2"
+ // }
+ // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
+ // "Hello2"\n"
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "{\n \"message\": \"Hello0\"\n}\n"
+ "{\n \"message\": \"Hello1\"\n}\n"
+ "{\n \"message\": \"Hello2\"\n}\n"));
+
+
std::cin.rdbuf(orig);
ShutdownServer();
}
@@ -479,6 +640,94 @@ TEST_F(GrpcToolTest, CallCommandBatchWithBadRequest) {
// Expected output: "message: "Hello0"\nmessage: "Hello2"\n"
EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
"message: \"Hello0\"\nmessage: \"Hello2\"\n"));
+
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+ ss.clear();
+ ss.seekg(0);
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_batch = true;
+ FLAGS_json_output= true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output= false;
+ FLAGS_batch = false;
+
+ // Expected output:
+ // {
+ // "message": "Hello0"
+ // }
+ // {
+ // "message": "Hello2"
+ // }
+ // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
+ // "Hello2"\n"
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "{\n \"message\": \"Hello0\"\n}\n"
+ "{\n \"message\": \"Hello2\"\n}\n"));
+
+ std::cin.rdbuf(orig);
+ ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandBatchJsonInputWithBadRequest) {
+ // Test input "grpc_cli call Echo"
+ std::stringstream output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
+ "{ \"message\": \"Hello0\"}"};
+
+ // Mock std::cin input "message: 1\n\n message: 'Hello2'\n\n"
+ std::streambuf* orig = std::cin.rdbuf();
+ std::istringstream ss("{ \"message\": 1 }\n\n { \"message\": \"Hello2\" }\n\n");
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_batch = true;
+ FLAGS_json_input = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_input = false;
+ FLAGS_batch = false;
+
+ // Expected output: "message: "Hello0"\nmessage: "Hello2"\n"
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
+
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+ ss.clear();
+ ss.seekg(0);
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_batch = true;
+ FLAGS_json_input = true;
+ FLAGS_json_output= true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output= false;
+ FLAGS_json_input = false;
+ FLAGS_batch = false;
+
+ // Expected output:
+ // {
+ // "message": "Hello0"
+ // }
+ // {
+ // "message": "Hello2"
+ // }
+ // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
+ // "Hello2"\n"
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "{\n \"message\": \"Hello0\"\n}\n"
+ "{\n \"message\": \"Hello2\"\n}\n"));
+
std::cin.rdbuf(orig);
ShutdownServer();
}
@@ -508,6 +757,33 @@ TEST_F(GrpcToolTest, CallCommandRequestStream) {
ShutdownServer();
}
+TEST_F(GrpcToolTest, CallCommandRequestStreamJsonInput) {
+ // Test input: grpc_cli call localhost:<port> RequestStream "{ \"message\":
+ // \"Hello0\"}"
+ std::stringstream output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+ "RequestStream", "{ \"message\": \"Hello0\" }"};
+
+ // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
+ std::streambuf* orig = std::cin.rdbuf();
+ std::istringstream ss("{ \"message\": \"Hello1\" }\n\n{ \"message\": \"Hello2\" }\n\n");
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_json_input = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_input = false;
+
+ // Expected output: "message: \"Hello0Hello1Hello2\""
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ "message: \"Hello0Hello1Hello2\""));
+ std::cin.rdbuf(orig);
+ ShutdownServer();
+}
+
TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequest) {
// Test input: grpc_cli call localhost:<port> RequestStream "message:
// 'Hello0'"
@@ -533,6 +809,33 @@ TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequest) {
ShutdownServer();
}
+TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequestJsonInput) {
+ // Test input: grpc_cli call localhost:<port> RequestStream "message:
+ // 'Hello0'"
+ std::stringstream output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+ "RequestStream", "{ \"message\": \"Hello0\" }"};
+
+ // Mock std::cin input "bad_field: 'Hello1'\n\n message: 'Hello2'\n\n"
+ std::streambuf* orig = std::cin.rdbuf();
+ std::istringstream ss("{ \"bad_field\": \"Hello1\" }\n\n{ \"message\": \"Hello2\" }\n\n");
+ std::cin.rdbuf(ss.rdbuf());
+
+ FLAGS_json_input = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_input = false;
+
+ // Expected output: "message: \"Hello0Hello2\""
+ EXPECT_TRUE(nullptr !=
+ strstr(output_stream.str().c_str(), "message: \"Hello0Hello2\""));
+ std::cin.rdbuf(orig);
+ ShutdownServer();
+}
+
TEST_F(GrpcToolTest, CallCommandResponseStream) {
// Test input: grpc_cli call localhost:<port> ResponseStream "message:
// 'Hello'"
@@ -554,6 +857,24 @@ TEST_F(GrpcToolTest, CallCommandResponseStream) {
expected_response_text.c_str()));
}
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+
+ FLAGS_json_output= true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output = false;
+
+ // Expected output: "{\n \"message\": \"Hello{n}\"\n}\n"
+ for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
+ grpc::string expected_response_text =
+ "{\n \"message\": \"Hello" + grpc::to_string(i) + "\"\n}\n";
+ EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
+ expected_response_text.c_str()));
+ }
+
ShutdownServer();
}
@@ -617,15 +938,28 @@ TEST_F(GrpcToolTest, ParseCommand) {
const grpc::string server_address = SetUpServer();
const char* argv[] = {"grpc_cli", "parse", server_address.c_str(),
- "grpc.testing.EchoResponse", ECHO_RESPONSE_MESSAGE};
+ "grpc.testing.EchoResponse", ECHO_RESPONSE_MESSAGE_TEXT_FORMAT};
FLAGS_binary_input = false;
FLAGS_binary_output = false;
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
- // Expected output: ECHO_RESPONSE_MESSAGE
- EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE));
+ // Expected output: ECHO_RESPONSE_MESSAGE_TEXT_FORMAT
+ EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
+
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+
+ FLAGS_json_output = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output = false;
+
+ // Expected output: ECHO_RESPONSE_MESSAGE_JSON_FORMAT
+ EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE_JSON_FORMAT));
// Parse text message to binary message and then parse it back to text message
output_stream.str(grpc::string());
@@ -645,13 +979,48 @@ TEST_F(GrpcToolTest, ParseCommand) {
std::placeholders::_1)));
// Expected output: ECHO_RESPONSE_MESSAGE
- EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE));
+ EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
FLAGS_binary_input = false;
FLAGS_binary_output = false;
ShutdownServer();
}
+TEST_F(GrpcToolTest, ParseCommandJsonFormat) {
+ // Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
+ // ECHO_RESPONSE_MESSAGE_JSON_FORMAT"
+ std::stringstream output_stream;
+ std::stringstream binary_output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "parse", server_address.c_str(),
+ "grpc.testing.EchoResponse", ECHO_RESPONSE_MESSAGE_JSON_FORMAT};
+
+ FLAGS_json_input = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+
+ // Expected output: ECHO_RESPONSE_MESSAGE_TEXT_FORMAT
+ EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
+
+ // with json_output
+ output_stream.str(grpc::string());
+ output_stream.clear();
+
+ FLAGS_json_output = true;
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ FLAGS_json_output = false;
+ FLAGS_json_input = false;
+
+ // Expected output: ECHO_RESPONSE_MESSAGE_JSON_FORMAT
+ EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), ECHO_RESPONSE_MESSAGE_JSON_FORMAT));
+
+ ShutdownServer();
+}
+
TEST_F(GrpcToolTest, TooFewArguments) {
// Test input "grpc_cli call Echo"
std::stringstream output_stream;
diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc
index a530ed1ffc..997808cbc3 100644
--- a/test/cpp/util/proto_file_parser.cc
+++ b/test/cpp/util/proto_file_parser.cc
@@ -216,7 +216,7 @@ bool ProtoFileParser::IsStreaming(const grpc::string& method, bool is_request) {
: method_desc->server_streaming();
}
-grpc::string ProtoFileParser::GetSerializedProtoFromMethod(
+grpc::string ProtoFileParser::GetSerializedProtoFromMethodTextFormat(
const grpc::string& method, const grpc::string& text_format_proto,
bool is_request) {
has_error_ = false;
@@ -224,10 +224,22 @@ grpc::string ProtoFileParser::GetSerializedProtoFromMethod(
if (has_error_) {
return "";
}
- return GetSerializedProtoFromMessageType(message_type_name,
+ return GetSerializedProtoFromMessageTypeTextFormat(message_type_name,
text_format_proto);
}
+grpc::string ProtoFileParser::GetSerializedProtoFromMethodJsonFormat(
+ const grpc::string& method, const grpc::string& json_format_proto,
+ bool is_request) {
+ has_error_ = false;
+ grpc::string message_type_name = GetMessageTypeFromMethod(method, is_request);
+ if (has_error_) {
+ return "";
+ }
+ return GetSerializedProtoFromMessageTypeJsonFormat(message_type_name,
+ json_format_proto);
+}
+
grpc::string ProtoFileParser::GetTextFormatFromMethod(
const grpc::string& method, const grpc::string& serialized_proto,
bool is_request) {
@@ -239,7 +251,18 @@ grpc::string ProtoFileParser::GetTextFormatFromMethod(
return GetTextFormatFromMessageType(message_type_name, serialized_proto);
}
-grpc::string ProtoFileParser::GetSerializedProtoFromMessageType(
+grpc::string ProtoFileParser::GetJsonFormatFromMethod(
+ const grpc::string& method, const grpc::string& serialized_proto,
+ bool is_request) {
+ has_error_ = false;
+ grpc::string message_type_name = GetMessageTypeFromMethod(method, is_request);
+ if (has_error_) {
+ return "";
+ }
+ return GetJsonFormatFromMessageType(message_type_name, serialized_proto);
+}
+
+grpc::string ProtoFileParser::GetSerializedProtoFromMessageTypeTextFormat(
const grpc::string& message_type_name,
const grpc::string& text_format_proto) {
has_error_ = false;
@@ -265,6 +288,32 @@ grpc::string ProtoFileParser::GetSerializedProtoFromMessageType(
return serialized;
}
+grpc::string ProtoFileParser::GetSerializedProtoFromMessageTypeJsonFormat(
+ const grpc::string& message_type_name,
+ const grpc::string& json_format_proto) {
+ has_error_ = false;
+ grpc::string serialized;
+ const protobuf::Descriptor* desc =
+ desc_pool_->FindMessageTypeByName(message_type_name);
+ if (!desc) {
+ LogError("Message type not found");
+ return "";
+ }
+ std::unique_ptr<grpc::protobuf::Message> msg(
+ dynamic_factory_->GetPrototype(desc)->New());
+
+ if (!grpc::protobuf::json::JsonStringToMessage(json_format_proto, msg.get()).ok()) {
+ LogError("Failed to parse json format to proto.");
+ return "";
+ }
+ bool ok = msg->SerializeToString(&serialized);
+ if (!ok) {
+ LogError("Failed to serialize proto.");
+ return "";
+ }
+ return serialized;
+}
+
grpc::string ProtoFileParser::GetTextFormatFromMessageType(
const grpc::string& message_type_name,
const grpc::string& serialized_proto) {
@@ -289,6 +338,32 @@ grpc::string ProtoFileParser::GetTextFormatFromMessageType(
return text_format;
}
+grpc::string ProtoFileParser::GetJsonFormatFromMessageType(
+ const grpc::string& message_type_name,
+ const grpc::string& serialized_proto) {
+ has_error_ = false;
+ const protobuf::Descriptor* desc =
+ desc_pool_->FindMessageTypeByName(message_type_name);
+ if (!desc) {
+ LogError("Message type not found");
+ return "";
+ }
+ std::unique_ptr<grpc::protobuf::Message> msg(
+ dynamic_factory_->GetPrototype(desc)->New());
+ if (!msg->ParseFromString(serialized_proto)) {
+ LogError("Failed to deserialize proto.");
+ return "";
+ }
+ grpc::string json_format;
+ grpc::protobuf::json::JsonPrintOptions jsonPrintOptions;
+ jsonPrintOptions.add_whitespace = true;
+ if (!grpc::protobuf::json::MessageToJsonString(*msg.get(), &json_format, jsonPrintOptions).ok()) {
+ LogError("Failed to print proto message to json format");
+ return "";
+ }
+ return json_format;
+}
+
void ProtoFileParser::LogError(const grpc::string& error_msg) {
if (!error_msg.empty()) {
std::cerr << error_msg << std::endl;
diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h
index eb1d793c2b..d2b2bd753e 100644
--- a/test/cpp/util/proto_file_parser.h
+++ b/test/cpp/util/proto_file_parser.h
@@ -53,22 +53,38 @@ class ProtoFileParser {
// used as the argument of Stub::Call()
grpc::string GetFormattedMethodName(const grpc::string& method);
- grpc::string GetSerializedProtoFromMethod(
+ grpc::string GetSerializedProtoFromMethodTextFormat(
const grpc::string& method, const grpc::string& text_format_proto,
bool is_request);
+ grpc::string GetSerializedProtoFromMethodJsonFormat(
+ const grpc::string& method, const grpc::string& json_format_proto,
+ bool is_request);
+
grpc::string GetTextFormatFromMethod(const grpc::string& method,
const grpc::string& serialized_proto,
bool is_request);
- grpc::string GetSerializedProtoFromMessageType(
+ grpc::string GetJsonFormatFromMethod(const grpc::string& method,
+ const grpc::string& serialized_proto,
+ bool is_request);
+
+ grpc::string GetSerializedProtoFromMessageTypeTextFormat(
const grpc::string& message_type_name,
const grpc::string& text_format_proto);
+ grpc::string GetSerializedProtoFromMessageTypeJsonFormat(
+ const grpc::string& message_type_name,
+ const grpc::string& json_format_proto);
+
grpc::string GetTextFormatFromMessageType(
const grpc::string& message_type_name,
const grpc::string& serialized_proto);
+ grpc::string GetJsonFormatFromMessageType(
+ const grpc::string& message_type_name,
+ const grpc::string& serialized_proto);
+
bool IsStreaming(const grpc::string& method, bool is_request);
bool HasError() const { return has_error_; }