diff options
Diffstat (limited to 'test/cpp/util')
-rw-r--r-- | test/cpp/util/create_test_channel.cc | 64 | ||||
-rw-r--r-- | test/cpp/util/create_test_channel.h | 4 | ||||
-rw-r--r-- | test/cpp/util/grpc_tool.cc | 149 | ||||
-rw-r--r-- | test/cpp/util/grpc_tool_test.cc | 50 | ||||
-rw-r--r-- | test/cpp/util/proto_file_parser.cc | 12 | ||||
-rw-r--r-- | test/cpp/util/proto_file_parser.h | 4 | ||||
-rw-r--r-- | test/cpp/util/test_credentials_provider.cc | 52 | ||||
-rw-r--r-- | test/cpp/util/test_credentials_provider.h | 50 |
8 files changed, 295 insertions, 90 deletions
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index fe8b5d5423..ad62e03490 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -35,11 +35,37 @@ #include <grpc++/create_channel.h> #include <grpc++/security/credentials.h> +#include <grpc/support/log.h> -#include "test/core/end2end/data/ssl_test_data.h" +#include "test/cpp/util/test_credentials_provider.h" namespace grpc { +namespace { + +const char kProdTlsCredentialsType[] = "prod_ssl"; + +class SslCredentialProvider : public testing::CredentialTypeProvider { + public: + std::shared_ptr<ChannelCredentials> GetChannelCredentials( + grpc::ChannelArguments* args) override { + return SslCredentials(SslCredentialsOptions()); + } + std::shared_ptr<ServerCredentials> GetServerCredentials() override { + return nullptr; + } +}; + +gpr_once g_once_init_add_prod_ssl_provider = GPR_ONCE_INIT; +// Register ssl with non-test roots type to the credentials provider. +void AddProdSslType() { + testing::GetCredentialsProvider()->AddSecureType( + kProdTlsCredentialsType, std::unique_ptr<testing::CredentialTypeProvider>( + new SslCredentialProvider)); +} + +} // namespace + // When ssl is enabled, if server is empty, override_hostname is used to // create channel. Otherwise, connect to server and override hostname if // override_hostname is provided. @@ -61,16 +87,22 @@ std::shared_ptr<Channel> CreateTestChannel( const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args) { ChannelArguments channel_args(args); + std::shared_ptr<ChannelCredentials> channel_creds; if (enable_ssl) { - const char* roots_certs = use_prod_roots ? "" : test_root_cert; - SslCredentialsOptions ssl_opts = {roots_certs, "", ""}; - - std::shared_ptr<ChannelCredentials> channel_creds = - SslCredentials(ssl_opts); - - if (!server.empty() && !override_hostname.empty()) { - channel_args.SetSslTargetNameOverride(override_hostname); + if (use_prod_roots) { + gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType); + channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( + kProdTlsCredentialsType, &channel_args); + if (!server.empty() && !override_hostname.empty()) { + channel_args.SetSslTargetNameOverride(override_hostname); + } + } else { + // override_hostname is discarded as the provider handles it. + channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( + testing::kTlsCredentialsType, &channel_args); } + GPR_ASSERT(channel_creds != nullptr); + const grpc::string& connect_to = server.empty() ? override_hostname : server; if (creds.get()) { @@ -103,4 +135,18 @@ std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server, return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false); } +std::shared_ptr<Channel> CreateTestChannel( + const grpc::string& server, const grpc::string& credential_type, + const std::shared_ptr<CallCredentials>& creds) { + ChannelArguments channel_args; + std::shared_ptr<ChannelCredentials> channel_creds = + testing::GetCredentialsProvider()->GetChannelCredentials(credential_type, + &channel_args); + GPR_ASSERT(channel_creds != nullptr); + if (creds.get()) { + channel_creds = CompositeChannelCredentials(channel_creds, creds); + } + return CreateCustomChannel(server, channel_creds, channel_args); +} + } // namespace grpc diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index 4ff666dc1b..ce71a97edb 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -59,6 +59,10 @@ std::shared_ptr<Channel> CreateTestChannel( const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args); +std::shared_ptr<Channel> CreateTestChannel( + const grpc::string& server, const grpc::string& credential_type, + const std::shared_ptr<CallCredentials>& creds); + } // namespace grpc #endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc index 03c33abe9f..b9900ca1b7 100644 --- a/test/cpp/util/grpc_tool.cc +++ b/test/cpp/util/grpc_tool.cc @@ -86,11 +86,12 @@ class GrpcTool { // callback); // bool PrintTypeId(int argc, const char** argv, GrpcToolOutputCallback // callback); - // bool ParseMessage(int argc, const char** argv, GrpcToolOutputCallback - // callback); - // bool ToText(int argc, const char** argv, GrpcToolOutputCallback callback); - // bool ToBinary(int argc, const char** argv, GrpcToolOutputCallback - // callback); + bool ParseMessage(int argc, const char** argv, const CliCredentials& cred, + GrpcToolOutputCallback callback); + bool ToText(int argc, const char** argv, const CliCredentials& cred, + GrpcToolOutputCallback callback); + bool ToBinary(int argc, const char** argv, const CliCredentials& cred, + GrpcToolOutputCallback callback); void SetPrintCommandMode(int exit_status) { print_command_usage_ = true; @@ -173,9 +174,9 @@ const Command ops[] = { {"list", BindWith5Args(&GrpcTool::ListServices), 1, 3}, {"call", BindWith5Args(&GrpcTool::CallMethod), 2, 3}, {"type", BindWith5Args(&GrpcTool::PrintType), 2, 2}, - // {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3}, - // {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3}, - // {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3}, + {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3}, + {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3}, + {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3}, }; void Usage(const grpc::string& msg) { @@ -185,9 +186,9 @@ void Usage(const grpc::string& msg) { " grpc_cli ls ... ; List services\n" " grpc_cli call ... ; Call method\n" " grpc_cli type ... ; Print type\n" - // " grpc_cli parse ... ; Parse message\n" - // " grpc_cli totext ... ; Convert binary message to text\n" - // " grpc_cli tobinary ... ; Convert text message to binary\n" + " grpc_cli parse ... ; Parse message\n" + " grpc_cli totext ... ; Convert binary message to text\n" + " grpc_cli tobinary ... ; Convert text message to binary\n" " grpc_cli help ... ; Print this message, or per-command usage\n" "\n", msg.c_str()); @@ -414,6 +415,7 @@ bool GrpcTool::CallMethod(int argc, const char** argv, grpc::string request_text; grpc::string server_address(argv[0]); grpc::string method_name(argv[1]); + grpc::string formatted_method_name; std::unique_ptr<grpc::testing::ProtoFileParser> parser; grpc::string serialized_request_proto; @@ -450,7 +452,9 @@ bool GrpcTool::CallMethod(int argc, const char** argv, if (FLAGS_binary_input) { serialized_request_proto = request_text; + formatted_method_name = method_name; } else { + formatted_method_name = parser->GetFormattedMethodName(method_name); serialized_request_proto = parser->GetSerializedProtoFromMethod( method_name, request_text, true /* is_request */); if (parser->HasError()) { @@ -466,9 +470,9 @@ bool GrpcTool::CallMethod(int argc, const char** argv, ParseMetadataFlag(&client_metadata); PrintMetadata(client_metadata, "Sending client initial metadata:"); grpc::Status status = grpc::testing::CliCall::Call( - channel, parser->GetFormatedMethodName(method_name), - serialized_request_proto, &serialized_response_proto, client_metadata, - &server_initial_metadata, &server_trailing_metadata); + channel, formatted_method_name, serialized_request_proto, + &serialized_response_proto, client_metadata, &server_initial_metadata, + &server_trailing_metadata); PrintMetadata(server_initial_metadata, "Received initial metadata from server:"); PrintMetadata(server_trailing_metadata, @@ -493,5 +497,122 @@ bool GrpcTool::CallMethod(int argc, const char** argv, 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 grpc diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc index 1ff8172306..33ce611a60 100644 --- a/test/cpp/util/grpc_tool_test.cc +++ b/test/cpp/util/grpc_tool_test.cc @@ -86,9 +86,18 @@ using grpc::testing::EchoResponse; " rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \ "{}\n" +#define ECHO_RESPONSE_MESSAGE \ + "message: \"echo\"\n" \ + "param {\n" \ + " host: \"localhost\"\n" \ + " peer: \"peer\"\n" \ + "}\n\n" + namespace grpc { namespace testing { +DECLARE_bool(binary_input); +DECLARE_bool(binary_output); DECLARE_bool(l); namespace { @@ -338,6 +347,47 @@ TEST_F(GrpcToolTest, CallCommand) { 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 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 3e524227e5..bc8a6083f4 100644 --- a/test/cpp/util/proto_file_parser.cc +++ b/test/cpp/util/proto_file_parser.cc @@ -172,19 +172,19 @@ grpc::string ProtoFileParser::GetFullMethodName(const grpc::string& method) { return method_descriptor->full_name(); } -grpc::string ProtoFileParser::GetFormatedMethodName( +grpc::string ProtoFileParser::GetFormattedMethodName( const grpc::string& method) { has_error_ = false; - grpc::string formated_method_name = GetFullMethodName(method); + grpc::string formatted_method_name = GetFullMethodName(method); if (has_error_) { return ""; } - size_t last_dot = formated_method_name.find_last_of('.'); + size_t last_dot = formatted_method_name.find_last_of('.'); if (last_dot != grpc::string::npos) { - formated_method_name[last_dot] = '/'; + formatted_method_name[last_dot] = '/'; } - formated_method_name.insert(formated_method_name.begin(), '/'); - return formated_method_name; + formatted_method_name.insert(formatted_method_name.begin(), '/'); + return formatted_method_name; } grpc::string ProtoFileParser::GetMessageTypeFromMethod( diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h index eda3991e72..c1070a37b5 100644 --- a/test/cpp/util/proto_file_parser.h +++ b/test/cpp/util/proto_file_parser.h @@ -64,9 +64,9 @@ class ProtoFileParser { // descriptor database queries. grpc::string GetFullMethodName(const grpc::string& method); - // Formated method name is in the form of /Service/Method, it's good to be + // Formatted method name is in the form of /Service/Method, it's good to be // used as the argument of Stub::Call() - grpc::string GetFormatedMethodName(const grpc::string& method); + grpc::string GetFormattedMethodName(const grpc::string& method); grpc::string GetSerializedProtoFromMethod( const grpc::string& method, const grpc::string& text_format_proto, diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 0456b96667..909b02a701 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -43,25 +43,9 @@ #include "test/core/end2end/data/ssl_test_data.h" namespace grpc { +namespace testing { namespace { -using grpc::testing::CredentialTypeProvider; - -// Provide test credentials. Thread-safe. -class CredentialsProvider { - public: - virtual ~CredentialsProvider() {} - - virtual void AddSecureType( - const grpc::string& type, - std::unique_ptr<CredentialTypeProvider> type_provider) = 0; - virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials( - const grpc::string& type, ChannelArguments* args) = 0; - virtual std::shared_ptr<ServerCredentials> GetServerCredentials( - const grpc::string& type) = 0; - virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0; -}; - class DefaultCredentialsProvider : public CredentialsProvider { public: ~DefaultCredentialsProvider() override {} @@ -145,37 +129,21 @@ class DefaultCredentialsProvider : public CredentialsProvider { added_secure_type_providers_; }; -gpr_once g_once_init_provider = GPR_ONCE_INIT; CredentialsProvider* g_provider = nullptr; -void CreateDefaultProvider() { g_provider = new DefaultCredentialsProvider; } - -CredentialsProvider* GetProvider() { - gpr_once_init(&g_once_init_provider, &CreateDefaultProvider); - return g_provider; -} - } // namespace -namespace testing { - -void AddSecureType(const grpc::string& type, - std::unique_ptr<CredentialTypeProvider> type_provider) { - GetProvider()->AddSecureType(type, std::move(type_provider)); -} - -std::shared_ptr<ChannelCredentials> GetChannelCredentials( - const grpc::string& type, ChannelArguments* args) { - return GetProvider()->GetChannelCredentials(type, args); -} - -std::shared_ptr<ServerCredentials> GetServerCredentials( - const grpc::string& type) { - return GetProvider()->GetServerCredentials(type); +CredentialsProvider* GetCredentialsProvider() { + if (g_provider == nullptr) { + g_provider = new DefaultCredentialsProvider; + } + return g_provider; } -std::vector<grpc::string> GetSecureCredentialsTypeList() { - return GetProvider()->GetSecureCredentialsTypeList(); +void SetCredentialsProvider(CredentialsProvider* provider) { + // For now, forbids overriding provider. + GPR_ASSERT(g_provider == nullptr); + g_provider = provider; } } // namespace testing diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h index 1fb311e556..0bc52ebe4d 100644 --- a/test/cpp/util/test_credentials_provider.h +++ b/test/cpp/util/test_credentials_provider.h @@ -59,23 +59,39 @@ class CredentialTypeProvider { virtual std::shared_ptr<ServerCredentials> GetServerCredentials() = 0; }; -// Add a secure type in addition to the defaults above -// (kInsecureCredentialsType, kTlsCredentialsType) that can be returned from the -// functions below. -void AddSecureType(const grpc::string& type, - std::unique_ptr<CredentialTypeProvider> type_provider); - -// Provide channel credentials according to the given type. Alter the channel -// arguments if needed. -std::shared_ptr<ChannelCredentials> GetChannelCredentials( - const grpc::string& type, ChannelArguments* args); - -// Provide server credentials according to the given type. -std::shared_ptr<ServerCredentials> GetServerCredentials( - const grpc::string& type); - -// Provide a list of secure credentials type. -std::vector<grpc::string> GetSecureCredentialsTypeList(); +// Provide test credentials. Thread-safe. +class CredentialsProvider { + public: + virtual ~CredentialsProvider() {} + + // Add a secure type in addition to the defaults. The default provider has + // (kInsecureCredentialsType, kTlsCredentialsType). + virtual void AddSecureType( + const grpc::string& type, + std::unique_ptr<CredentialTypeProvider> type_provider) = 0; + + // Provide channel credentials according to the given type. Alter the channel + // arguments if needed. Return nullptr if type is not registered. + virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials( + const grpc::string& type, ChannelArguments* args) = 0; + + // Provide server credentials according to the given type. + // Return nullptr if type is not registered. + virtual std::shared_ptr<ServerCredentials> GetServerCredentials( + const grpc::string& type) = 0; + + // Provide a list of secure credentials type. + virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0; +}; + +// Get the current provider. Create a default one if not set. +// Not thread-safe. +CredentialsProvider* GetCredentialsProvider(); + +// Set the global provider. Takes ownership. The previous set provider will be +// destroyed. +// Not thread-safe. +void SetCredentialsProvider(CredentialsProvider* provider); } // namespace testing } // namespace grpc |