Merge pull request #7913 from y-zeng/cli_parse

gRPC CLI parse, tobinary, totext commands
pull/9122/head
Yuchen Zeng 8 years ago committed by GitHub
commit 13a16c1ba5
  1. 140
      test/cpp/util/grpc_tool.cc
  2. 50
      test/cpp/util/grpc_tool_test.cc

@ -86,11 +86,12 @@ class GrpcTool {
// callback); // callback);
// bool PrintTypeId(int argc, const char** argv, GrpcToolOutputCallback // bool PrintTypeId(int argc, const char** argv, GrpcToolOutputCallback
// callback); // callback);
// bool ParseMessage(int argc, const char** argv, GrpcToolOutputCallback bool ParseMessage(int argc, const char** argv, const CliCredentials& cred,
// callback); GrpcToolOutputCallback callback);
// bool ToText(int argc, const char** argv, GrpcToolOutputCallback callback); bool ToText(int argc, const char** argv, const CliCredentials& cred,
// bool ToBinary(int argc, const char** argv, GrpcToolOutputCallback GrpcToolOutputCallback callback);
// callback); bool ToBinary(int argc, const char** argv, const CliCredentials& cred,
GrpcToolOutputCallback callback);
void SetPrintCommandMode(int exit_status) { void SetPrintCommandMode(int exit_status) {
print_command_usage_ = true; print_command_usage_ = true;
@ -173,9 +174,9 @@ const Command ops[] = {
{"list", BindWith5Args(&GrpcTool::ListServices), 1, 3}, {"list", BindWith5Args(&GrpcTool::ListServices), 1, 3},
{"call", BindWith5Args(&GrpcTool::CallMethod), 2, 3}, {"call", BindWith5Args(&GrpcTool::CallMethod), 2, 3},
{"type", BindWith5Args(&GrpcTool::PrintType), 2, 2}, {"type", BindWith5Args(&GrpcTool::PrintType), 2, 2},
// {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3}, {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3},
// {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3}, {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3},
// {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3}, {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3},
}; };
void Usage(const grpc::string& msg) { void Usage(const grpc::string& msg) {
@ -185,9 +186,9 @@ void Usage(const grpc::string& msg) {
" grpc_cli ls ... ; List services\n" " grpc_cli ls ... ; List services\n"
" grpc_cli call ... ; Call method\n" " grpc_cli call ... ; Call method\n"
" grpc_cli type ... ; Print type\n" " grpc_cli type ... ; Print type\n"
// " grpc_cli parse ... ; Parse message\n" " grpc_cli parse ... ; Parse message\n"
// " grpc_cli totext ... ; Convert binary message to text\n" " grpc_cli totext ... ; Convert binary message to text\n"
// " grpc_cli tobinary ... ; Convert text message to binary\n" " grpc_cli tobinary ... ; Convert text message to binary\n"
" grpc_cli help ... ; Print this message, or per-command usage\n" " grpc_cli help ... ; Print this message, or per-command usage\n"
"\n", "\n",
msg.c_str()); msg.c_str());
@ -496,5 +497,122 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
return callback(output_ss.str()); return callback(output_ss.str());
} }
bool GrpcTool::ParseMessage(int argc, const char** argv,
const CliCredentials& cred,
GrpcToolOutputCallback callback) {
CommandUsage(
"Parse message\n"
" grpc_cli parse <address> <type> [<message>]\n"
" <address> ; host:port\n"
" <type> ; Protocol buffer type name\n"
" <message> ; Text protobuffer (overrides --infile)\n"
" --protofiles ; Comma separated proto files used as a"
" fallback when parsing request/response\n"
" --proto_path ; The search path of proto files, valid"
" only when --protofiles is given\n"
" --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" +
cred.GetCredentialUsage());
std::stringstream output_ss;
grpc::string message_text;
grpc::string server_address(argv[0]);
grpc::string type_name(argv[1]);
std::unique_ptr<grpc::testing::ProtoFileParser> parser;
grpc::string serialized_request_proto;
if (argc == 3) {
message_text = argv[2];
if (!FLAGS_infile.empty()) {
fprintf(stderr, "warning: message given in argv, ignoring --infile.\n");
}
} else {
std::stringstream input_stream;
if (FLAGS_infile.empty()) {
if (isatty(STDIN_FILENO)) {
fprintf(stderr, "reading request message from stdin...\n");
}
input_stream << std::cin.rdbuf();
} else {
std::ifstream input_file(FLAGS_infile, std::ios::in | std::ios::binary);
input_stream << input_file.rdbuf();
input_file.close();
}
message_text = input_stream.str();
}
if (!FLAGS_binary_input || !FLAGS_binary_output) {
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, cred.GetCredentials());
parser.reset(
new grpc::testing::ProtoFileParser(FLAGS_remotedb ? channel : nullptr,
FLAGS_proto_path, FLAGS_protofiles));
if (parser->HasError()) {
return false;
}
}
if (FLAGS_binary_input) {
serialized_request_proto = message_text;
} else {
serialized_request_proto =
parser->GetSerializedProtoFromMessageType(type_name, message_text);
if (parser->HasError()) {
return false;
}
}
if (FLAGS_binary_output) {
output_ss << serialized_request_proto;
} else {
grpc::string output_text = parser->GetTextFormatFromMessageType(
type_name, serialized_request_proto);
if (parser->HasError()) {
return false;
}
output_ss << output_text << std::endl;
}
return callback(output_ss.str());
}
bool GrpcTool::ToText(int argc, const char** argv, const CliCredentials& cred,
GrpcToolOutputCallback callback) {
CommandUsage(
"Convert binary message to text\n"
" grpc_cli totext <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;
return ParseMessage(argc, argv, cred, callback);
}
bool GrpcTool::ToBinary(int argc, const char** argv, const CliCredentials& cred,
GrpcToolOutputCallback callback) {
CommandUsage(
"Convert text message to binary\n"
" grpc_cli tobinary <protofiles> <type> [<message>]\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 = false;
FLAGS_binary_output = true;
return ParseMessage(argc, argv, cred, callback);
}
} // namespace testing } // namespace testing
} // namespace grpc } // namespace grpc

@ -86,9 +86,18 @@ using grpc::testing::EchoResponse;
" rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \ " rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
"{}\n" "{}\n"
#define ECHO_RESPONSE_MESSAGE \
"message: \"echo\"\n" \
"param {\n" \
" host: \"localhost\"\n" \
" peer: \"peer\"\n" \
"}\n\n"
namespace grpc { namespace grpc {
namespace testing { namespace testing {
DECLARE_bool(binary_input);
DECLARE_bool(binary_output);
DECLARE_bool(l); DECLARE_bool(l);
namespace { namespace {
@ -338,6 +347,47 @@ TEST_F(GrpcToolTest, CallCommand) {
ShutdownServer(); ShutdownServer();
} }
TEST_F(GrpcToolTest, ParseCommand) {
// Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
// ECHO_RESPONSE_MESSAGE"
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};
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));
// Parse text message to binary message and then parse it back to text message
output_stream.str(grpc::string());
output_stream.clear();
FLAGS_binary_output = true;
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
grpc::string binary_data = output_stream.str();
output_stream.str(grpc::string());
output_stream.clear();
argv[4] = binary_data.c_str();
FLAGS_binary_input = true;
FLAGS_binary_output = false;
EXPECT_TRUE(0 == GrpcToolMainLib(5, 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));
ShutdownServer();
}
TEST_F(GrpcToolTest, TooFewArguments) { TEST_F(GrpcToolTest, TooFewArguments) {
// Test input "grpc_cli call Echo" // Test input "grpc_cli call Echo"
std::stringstream output_stream; std::stringstream output_stream;

Loading…
Cancel
Save