Merge pull request #18156 from mkbehr/interop-client-additional-metadata

Let the c++ interop_client send additional metadata, controlled by a flag.
pull/18353/head
Yang Gao 6 years ago committed by GitHub
commit 2ee9795183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 88
      test/cpp/interop/client.cc
  2. 15
      test/cpp/interop/client_helper.cc
  3. 42
      test/cpp/interop/client_helper.h
  4. 122
      test/cpp/util/create_test_channel.cc
  5. 32
      test/cpp/util/create_test_channel.h

@ -92,17 +92,101 @@ DEFINE_int32(soak_iterations, 1000,
DEFINE_int32(iteration_interval, 10,
"The interval in seconds between rpcs. This is used by "
"long_connection test");
DEFINE_string(additional_metadata, "",
"Additional metadata to send in each request, as a "
"semicolon-separated list of key:value pairs.");
using grpc::testing::CreateChannelForTestCase;
using grpc::testing::GetServiceAccountJsonKey;
using grpc::testing::UpdateActions;
namespace {
// Parse the contents of FLAGS_additional_metadata into a map. Allow
// alphanumeric characters and dashes in keys, and any character but semicolons
// in values. Convert keys to lowercase. On failure, log an error and return
// false.
bool ParseAdditionalMetadataFlag(
const grpc::string& flag,
std::multimap<grpc::string, grpc::string>* additional_metadata) {
size_t start_pos = 0;
while (start_pos < flag.length()) {
size_t colon_pos = flag.find(':', start_pos);
if (colon_pos == grpc::string::npos) {
gpr_log(GPR_ERROR,
"Couldn't parse metadata flag: extra characters at end of flag");
return false;
}
size_t semicolon_pos = flag.find(';', colon_pos);
grpc::string key = flag.substr(start_pos, colon_pos - start_pos);
grpc::string value =
flag.substr(colon_pos + 1, semicolon_pos - colon_pos - 1);
constexpr char alphanum_and_hyphen[] =
"-0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (key.find_first_not_of(alphanum_and_hyphen) != grpc::string::npos) {
gpr_log(GPR_ERROR,
"Couldn't parse metadata flag: key contains characters other "
"than alphanumeric and hyphens: %s",
key.c_str());
return false;
}
// Convert to lowercase.
for (char& c : key) {
if (c >= 'A' && c <= 'Z') {
c += ('a' - 'A');
}
}
gpr_log(GPR_INFO, "Adding additional metadata with key %s and value %s",
key.c_str(), value.c_str());
additional_metadata->insert({key, value});
if (semicolon_pos == grpc::string::npos) {
break;
} else {
start_pos = semicolon_pos + 1;
}
}
return true;
}
} // namespace
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
gpr_log(GPR_INFO, "Testing these cases: %s", FLAGS_test_case.c_str());
int ret = 0;
grpc::testing::ChannelCreationFunc channel_creation_func =
std::bind(&CreateChannelForTestCase, FLAGS_test_case);
grpc::testing::ChannelCreationFunc channel_creation_func;
grpc::string test_case = FLAGS_test_case;
if (FLAGS_additional_metadata == "") {
channel_creation_func = [test_case]() {
return CreateChannelForTestCase(test_case);
};
} else {
std::multimap<grpc::string, grpc::string> additional_metadata;
if (!ParseAdditionalMetadataFlag(FLAGS_additional_metadata,
&additional_metadata)) {
return 1;
}
channel_creation_func = [test_case, additional_metadata]() {
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>
factories;
factories.emplace_back(
new grpc::testing::AdditionalMetadataInterceptorFactory(
additional_metadata));
return CreateChannelForTestCase(test_case, std::move(factories));
};
}
grpc::testing::InteropClient client(channel_creation_func, true,
FLAGS_do_not_abort_on_transient_failures);

@ -79,7 +79,10 @@ void UpdateActions(
std::unordered_map<grpc::string, std::function<bool()>>* actions) {}
std::shared_ptr<Channel> CreateChannelForTestCase(
const grpc::string& test_case) {
const grpc::string& test_case,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
GPR_ASSERT(FLAGS_server_port);
const int host_port_buf_size = 1024;
char host_port[host_port_buf_size];
@ -107,9 +110,15 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
transport_security security_type =
FLAGS_use_alts ? ALTS : (FLAGS_use_tls ? TLS : INSECURE);
return CreateTestChannel(host_port, FLAGS_server_host_override,
security_type, !FLAGS_use_test_ca, creds);
security_type, !FLAGS_use_test_ca, creds,
std::move(interceptor_creators));
} else {
return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds);
if (interceptor_creators.empty()) {
return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds);
} else {
return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds,
std::move(interceptor_creators));
}
}
}

@ -39,7 +39,10 @@ void UpdateActions(
std::unordered_map<grpc::string, std::function<bool()>>* actions);
std::shared_ptr<Channel> CreateChannelForTestCase(
const grpc::string& test_case);
const grpc::string& test_case,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators = {});
class InteropClientContextInspector {
public:
@ -59,6 +62,43 @@ class InteropClientContextInspector {
const ::grpc::ClientContext& context_;
};
class AdditionalMetadataInterceptor : public experimental::Interceptor {
public:
AdditionalMetadataInterceptor(
std::multimap<grpc::string, grpc::string> additional_metadata)
: additional_metadata_(std::move(additional_metadata)) {}
void Intercept(experimental::InterceptorBatchMethods* methods) override {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) {
std::multimap<grpc::string, grpc::string>* metadata =
methods->GetSendInitialMetadata();
for (const auto& entry : additional_metadata_) {
metadata->insert(entry);
}
}
methods->Proceed();
}
private:
const std::multimap<grpc::string, grpc::string> additional_metadata_;
};
class AdditionalMetadataInterceptorFactory
: public experimental::ClientInterceptorFactoryInterface {
public:
AdditionalMetadataInterceptorFactory(
std::multimap<grpc::string, grpc::string> additional_metadata)
: additional_metadata_(std::move(additional_metadata)) {}
experimental::Interceptor* CreateClientInterceptor(
experimental::ClientRpcInfo* info) override {
return new AdditionalMetadataInterceptor(additional_metadata_);
}
const std::multimap<grpc::string, grpc::string> additional_metadata_;
};
} // namespace testing
} // namespace grpc

@ -71,10 +71,73 @@ std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& override_hostname, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args) {
return CreateTestChannel(server, cred_type, override_hostname, use_prod_roots,
creds, args,
/*interceptor_creators=*/{});
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args) {
return CreateTestChannel(server, override_hostname, security_type,
use_prod_roots, creds, args,
/*interceptor_creators=*/{});
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds) {
return CreateTestChannel(server, override_hostname, security_type,
use_prod_roots, creds, ChannelArguments());
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots) {
return CreateTestChannel(server, override_hostname, security_type,
use_prod_roots, std::shared_ptr<CallCredentials>());
}
// Shortcut for end2end and interop tests.
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, testing::transport_security security_type) {
return CreateTestChannel(server, "foo.test.google.fr", security_type, 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);
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& cred_type,
const grpc::string& override_hostname, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
ChannelArguments channel_args(args);
std::shared_ptr<ChannelCredentials> channel_creds;
if (cred_type.empty()) {
return CreateCustomChannel(server, InsecureChannelCredentials(), args);
if (interceptor_creators.empty()) {
return CreateCustomChannel(server, InsecureChannelCredentials(), args);
} else {
return experimental::CreateCustomChannelWithInterceptors(
server, InsecureChannelCredentials(), args,
std::move(interceptor_creators));
}
} else if (cred_type == testing::kTlsCredentialsType) { // cred_type == "ssl"
if (use_prod_roots) {
gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType);
@ -95,54 +158,62 @@ std::shared_ptr<Channel> CreateTestChannel(
if (creds.get()) {
channel_creds = CompositeChannelCredentials(channel_creds, creds);
}
return CreateCustomChannel(connect_to, channel_creds, channel_args);
if (interceptor_creators.empty()) {
return CreateCustomChannel(connect_to, channel_creds, channel_args);
} else {
return experimental::CreateCustomChannelWithInterceptors(
connect_to, channel_creds, channel_args,
std::move(interceptor_creators));
}
} else {
channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
cred_type, &channel_args);
GPR_ASSERT(channel_creds != nullptr);
return CreateCustomChannel(server, channel_creds, args);
if (interceptor_creators.empty()) {
return CreateCustomChannel(server, channel_creds, args);
} else {
return experimental::CreateCustomChannelWithInterceptors(
server, channel_creds, args, std::move(interceptor_creators));
}
}
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args) {
grpc::string type =
const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
grpc::string credential_type =
security_type == testing::ALTS
? testing::kAltsCredentialsType
: (security_type == testing::TLS ? testing::kTlsCredentialsType
: testing::kInsecureCredentialsType);
return CreateTestChannel(server, type, override_hostname, use_prod_roots,
creds, args);
return CreateTestChannel(server, credential_type, override_hostname,
use_prod_roots, creds, args,
std::move(interceptor_creators));
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds) {
return CreateTestChannel(server, override_hostname, security_type,
use_prod_roots, creds, ChannelArguments());
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots) {
const std::shared_ptr<CallCredentials>& creds,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
return CreateTestChannel(server, override_hostname, security_type,
use_prod_roots, std::shared_ptr<CallCredentials>());
}
// Shortcut for end2end and interop tests.
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, testing::transport_security security_type) {
return CreateTestChannel(server, "foo.test.google.fr", security_type, false);
use_prod_roots, creds, ChannelArguments(),
std::move(interceptor_creators));
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& credential_type,
const std::shared_ptr<CallCredentials>& creds) {
const std::shared_ptr<CallCredentials>& creds,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
ChannelArguments channel_args;
std::shared_ptr<ChannelCredentials> channel_creds =
testing::GetCredentialsProvider()->GetChannelCredentials(credential_type,
@ -151,7 +222,8 @@ std::shared_ptr<Channel> CreateTestChannel(
if (creds.get()) {
channel_creds = CompositeChannelCredentials(channel_creds, creds);
}
return CreateCustomChannel(server, channel_creds, channel_args);
return experimental::CreateCustomChannelWithInterceptors(
server, channel_creds, channel_args, std::move(interceptor_creators));
}
} // namespace grpc

@ -21,6 +21,7 @@
#include <memory>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/security/credentials.h>
namespace grpc {
@ -60,6 +61,37 @@ std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& credential_type,
const std::shared_ptr<CallCredentials>& creds);
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& cred_type,
const grpc::string& override_hostname, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds, const ChannelArguments& args,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& credential_type,
const std::shared_ptr<CallCredentials>& creds,
std::vector<
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H

Loading…
Cancel
Save