aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/cpp')
-rw-r--r--test/cpp/end2end/async_end2end_test.cc36
-rw-r--r--test/cpp/end2end/end2end_test.cc37
-rw-r--r--test/cpp/end2end/generic_end2end_test.cc2
-rw-r--r--test/cpp/end2end/hybrid_end2end_test.cc171
-rw-r--r--test/cpp/end2end/proto_server_reflection_test.cc166
-rw-r--r--test/cpp/end2end/server_builder_plugin_test.cc52
-rw-r--r--test/cpp/end2end/test_service_impl.cc3
-rw-r--r--test/cpp/end2end/thread_stress_test.cc4
-rw-r--r--test/cpp/end2end/zookeeper_test.cc2
-rw-r--r--test/cpp/interop/client.cc101
-rw-r--r--test/cpp/interop/interop_client.cc388
-rw-r--r--test/cpp/interop/interop_client.h12
-rw-r--r--test/cpp/interop/interop_server.cc (renamed from test/cpp/interop/server_main.cc)143
-rw-r--r--test/cpp/interop/metrics_client.cc2
-rw-r--r--test/cpp/interop/rnd.datbin524288 -> 0 bytes
-rw-r--r--test/cpp/interop/server_helper.cc4
-rw-r--r--test/cpp/interop/server_helper.h1
-rw-r--r--test/cpp/interop/stress_interop_client.cc14
-rw-r--r--test/cpp/interop/stress_interop_client.h36
-rw-r--r--test/cpp/qps/client.h35
-rw-r--r--test/cpp/qps/client_async.cc16
-rw-r--r--test/cpp/qps/client_sync.cc1
-rw-r--r--test/cpp/qps/driver.cc10
-rw-r--r--test/cpp/qps/parse_json.cc19
-rw-r--r--test/cpp/qps/parse_json.h5
-rw-r--r--test/cpp/qps/perf_db_client.cc140
-rw-r--r--test/cpp/qps/perf_db_client.h113
-rw-r--r--test/cpp/qps/qps_json_driver.cc2
-rw-r--r--test/cpp/qps/report.cc18
-rw-r--r--test/cpp/qps/report.h1
-rw-r--r--test/cpp/qps/server_async.cc2
-rw-r--r--test/cpp/qps/server_sync.cc1
-rw-r--r--test/cpp/util/byte_buffer_proto_helper.h2
-rw-r--r--test/cpp/util/cli_call.cc2
-rw-r--r--test/cpp/util/grpc_cli.cc129
-rw-r--r--test/cpp/util/metrics_server.cc4
-rw-r--r--test/cpp/util/proto_file_parser.cc178
-rw-r--r--test/cpp/util/proto_file_parser.h85
-rw-r--r--test/cpp/util/proto_reflection_descriptor_database.cc316
-rw-r--r--test/cpp/util/proto_reflection_descriptor_database.h131
-rw-r--r--test/cpp/util/test_credentials_provider.cc59
41 files changed, 1650 insertions, 793 deletions
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index 45f5eb1ddd..6c7eae53a4 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -31,6 +31,7 @@
*
*/
+#include <cinttypes>
#include <memory>
#include <thread>
@@ -207,12 +208,11 @@ class ServerBuilderSyncPluginDisabler : public ::grpc::ServerBuilderOption {
public:
void UpdateArguments(ChannelArguments* arg) GRPC_OVERRIDE {}
- void UpdatePlugins(
- std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>>* plugins)
+ void UpdatePlugins(std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins)
GRPC_OVERRIDE {
auto plugin = plugins->begin();
while (plugin != plugins->end()) {
- if ((*plugin).second->has_sync_methods()) {
+ if ((*plugin)->has_sync_methods()) {
plugins->erase(plugin++);
} else {
plugin++;
@@ -229,13 +229,17 @@ class TestScenario {
credentials_type(creds_type),
message_content(content) {}
void Log() const {
- gpr_log(GPR_INFO,
- "Scenario: disable_blocking %d, credentials %s, message size %d",
- disable_blocking, credentials_type.c_str(), message_content.size());
+ gpr_log(
+ GPR_INFO,
+ "Scenario: disable_blocking %d, credentials %s, message size %" PRIuPTR,
+ disable_blocking, credentials_type.c_str(), message_content.size());
}
bool disable_blocking;
- const grpc::string credentials_type;
- const grpc::string message_content;
+ // Although the below grpc::string's are logically const, we can't declare
+ // them const because of a limitation in the way old compilers (e.g., gcc-4.4)
+ // manage vector insertion using a copy constructor
+ grpc::string credentials_type;
+ grpc::string message_content;
};
class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
@@ -819,7 +823,7 @@ TEST_P(AsyncEnd2endTest, ServerCheckCancellation) {
EXPECT_TRUE(srv_ctx.IsCancelled());
response_reader->Finish(&recv_response, &recv_status, tag(4));
- Verifier(GetParam().disable_blocking).Expect(4, false).Verify(cq_.get());
+ Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get());
EXPECT_EQ(StatusCode::CANCELLED, recv_status.error_code());
}
@@ -881,7 +885,7 @@ TEST_P(AsyncEnd2endTest, UnimplementedRpc) {
stub->AsyncUnimplemented(&cli_ctx, send_request, cq_.get()));
response_reader->Finish(&recv_response, &recv_status, tag(4));
- Verifier(GetParam().disable_blocking).Expect(4, false).Verify(cq_.get());
+ Verifier(GetParam().disable_blocking).Expect(4, true).Verify(cq_.get());
EXPECT_EQ(StatusCode::UNIMPLEMENTED, recv_status.error_code());
EXPECT_EQ("", recv_status.error_message());
@@ -939,7 +943,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// Client sends 3 messages (tags 3, 4 and 5)
for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
- send_request.set_message("Ping " + std::to_string(tag_idx));
+ send_request.set_message("Ping " + grpc::to_string(tag_idx));
cli_stream->Write(send_request, tag(tag_idx));
Verifier(GetParam().disable_blocking)
.Expect(tag_idx, true)
@@ -1026,9 +1030,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// Client will see the cancellation
cli_stream->Finish(&recv_status, tag(10));
- // TODO(sreek): The expectation here should be true. This is a bug (github
- // issue #4972)
- Verifier(GetParam().disable_blocking).Expect(10, false).Verify(cq_.get());
+ Verifier(GetParam().disable_blocking).Expect(10, true).Verify(cq_.get());
EXPECT_FALSE(recv_status.ok());
EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code());
}
@@ -1107,7 +1109,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// Server sends three messages (tags 3, 4 and 5)
// But if want_done tag is true, we might also see tag 11
for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
- send_response.set_message("Pong " + std::to_string(tag_idx));
+ send_response.set_message("Pong " + grpc::to_string(tag_idx));
srv_stream.Write(send_response, tag(tag_idx));
// Note that we'll add something to the verifier and verify that
// something was seen, but it might be tag 11 and not what we
@@ -1398,9 +1400,9 @@ std::vector<TestScenario> CreateTestScenarios(bool test_disable_blocking,
for (auto cred = credentials_types.begin(); cred != credentials_types.end();
++cred) {
for (auto msg = messages.begin(); msg != messages.end(); msg++) {
- scenarios.push_back(TestScenario(false, *cred, *msg));
+ scenarios.emplace_back(false, *cred, *msg);
if (test_disable_blocking) {
- scenarios.push_back(TestScenario(true, *cred, *msg));
+ scenarios.emplace_back(true, *cred, *msg);
}
}
}
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index f52aa52f39..354a59cedd 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -75,6 +75,8 @@ bool CheckIsLocalhost(const grpc::string& addr) {
addr.substr(0, kIpv6.size()) == kIpv6;
}
+const char kTestCredsPluginErrorMsg[] = "Could not find plugin metadata.";
+
class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
public:
static const char kMetadataKey[];
@@ -99,7 +101,7 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
metadata->insert(std::make_pair(kMetadataKey, metadata_value_));
return Status::OK;
} else {
- return Status(StatusCode::NOT_FOUND, "Could not find plugin metadata.");
+ return Status(StatusCode::NOT_FOUND, kTestCredsPluginErrorMsg);
}
}
@@ -199,7 +201,10 @@ class TestScenario {
credentials_type.c_str());
}
bool use_proxy;
- const grpc::string credentials_type;
+ // Although the below grpc::string is logically const, we can't declare
+ // them const because of a limitation in the way old compilers (e.g., gcc-4.4)
+ // manage vector insertion using a copy constructor
+ grpc::string credentials_type;
};
class End2endTest : public ::testing::TestWithParam<TestScenario> {
@@ -329,7 +334,7 @@ class End2endServerTryCancelTest : public End2endTest {
// Send server_try_cancel value in the client metadata
context.AddMetadata(kServerTryCancelRequest,
- std::to_string(server_try_cancel));
+ grpc::to_string(server_try_cancel));
auto stream = stub_->RequestStream(&context, &response);
@@ -402,7 +407,7 @@ class End2endServerTryCancelTest : public End2endTest {
// Send server_try_cancel in the client metadata
context.AddMetadata(kServerTryCancelRequest,
- std::to_string(server_try_cancel));
+ grpc::to_string(server_try_cancel));
request.set_message("hello");
auto stream = stub_->ResponseStream(&context, request);
@@ -413,7 +418,7 @@ class End2endServerTryCancelTest : public End2endTest {
break;
}
EXPECT_EQ(response.message(),
- request.message() + std::to_string(num_msgs_read));
+ request.message() + grpc::to_string(num_msgs_read));
num_msgs_read++;
}
gpr_log(GPR_INFO, "Read %d messages", num_msgs_read);
@@ -479,14 +484,14 @@ class End2endServerTryCancelTest : public End2endTest {
// Send server_try_cancel in the client metadata
context.AddMetadata(kServerTryCancelRequest,
- std::to_string(server_try_cancel));
+ grpc::to_string(server_try_cancel));
auto stream = stub_->BidiStream(&context);
int num_msgs_read = 0;
int num_msgs_sent = 0;
while (num_msgs_sent < num_messages) {
- request.set_message("hello " + std::to_string(num_msgs_sent));
+ request.set_message("hello " + grpc::to_string(num_msgs_sent));
if (!stream->Write(request)) {
break;
}
@@ -548,7 +553,7 @@ TEST_P(End2endServerTryCancelTest, RequestEchoServerCancel) {
ClientContext context;
context.AddMetadata(kServerTryCancelRequest,
- std::to_string(CANCEL_BEFORE_PROCESSING));
+ grpc::to_string(CANCEL_BEFORE_PROCESSING));
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code());
@@ -1014,6 +1019,16 @@ TEST_P(ProxyEnd2endTest, SimpleRpc) {
SendRpc(stub_.get(), 1, false);
}
+TEST_P(ProxyEnd2endTest, SimpleRpcWithEmptyMessages) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+
+ ClientContext context;
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+}
+
TEST_P(ProxyEnd2endTest, MultipleRpcs) {
ResetStub();
std::vector<std::thread*> threads;
@@ -1318,6 +1333,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) {
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+ EXPECT_EQ(s.error_message(), kTestCredsPluginErrorMsg);
}
TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
@@ -1375,6 +1391,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) {
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+ EXPECT_EQ(s.error_message(), kTestCredsPluginErrorMsg);
}
TEST_P(SecureEnd2endTest, ClientAuthContext) {
@@ -1421,9 +1438,9 @@ std::vector<TestScenario> CreateTestScenarios(bool use_proxy,
}
for (auto it = credentials_types.begin(); it != credentials_types.end();
++it) {
- scenarios.push_back(TestScenario(false, *it));
+ scenarios.emplace_back(false, *it);
if (use_proxy) {
- scenarios.push_back(TestScenario(true, *it));
+ scenarios.emplace_back(true, *it);
}
}
return scenarios;
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index d0cf6aea9d..57efa5fa17 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -38,7 +38,7 @@
#include <grpc++/create_channel.h>
#include <grpc++/generic/async_generic_service.h>
#include <grpc++/generic/generic_stub.h>
-#include <grpc++/impl/proto_utils.h>
+#include <grpc++/impl/codegen/proto_utils.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc
index 2c05db345b..7e0c0e8a7c 100644
--- a/test/cpp/end2end/hybrid_end2end_test.cc
+++ b/test/cpp/end2end/hybrid_end2end_test.cc
@@ -347,47 +347,50 @@ class HybridEnd2endTest : public ::testing::Test {
}
grpc::testing::UnimplementedService::Service unimplemented_service_;
- std::vector<std::unique_ptr<ServerCompletionQueue> > cqs_;
+ std::vector<std::unique_ptr<ServerCompletionQueue>> cqs_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<Server> server_;
std::ostringstream server_address_;
};
TEST_F(HybridEnd2endTest, AsyncEcho) {
- EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> service;
+ typedef EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> SType;
+ SType service;
SetUpServer(&service, nullptr, nullptr);
ResetStub();
- std::thread echo_handler_thread(
- [this, &service] { HandleEcho(&service, cqs_[0].get(), false); });
+ std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(),
+ false);
TestAllMethods();
echo_handler_thread.join();
}
TEST_F(HybridEnd2endTest, AsyncEchoRequestStream) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithAsyncMethod_Echo<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithAsyncMethod_Echo<TestServiceImpl>>
+ SType;
+ SType service;
SetUpServer(&service, nullptr, nullptr);
ResetStub();
- std::thread echo_handler_thread(
- [this, &service] { HandleEcho(&service, cqs_[0].get(), false); });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread echo_handler_thread(HandleEcho<SType>, &service, cqs_[0].get(),
+ false);
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
TestAllMethods();
echo_handler_thread.join();
request_stream_handler_thread.join();
}
TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>
+ SType;
+ SType service;
SetUpServer(&service, nullptr, nullptr);
ResetStub();
- std::thread response_stream_handler_thread(
- [this, &service] { HandleServerStreaming(&service, cqs_[0].get()); });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread response_stream_handler_thread(HandleServerStreaming<SType>,
+ &service, cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
TestAllMethods();
response_stream_handler_thread.join();
request_stream_handler_thread.join();
@@ -395,16 +398,17 @@ TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream) {
// Add a second service with one sync method.
TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_SyncDupService) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>
+ SType;
+ SType service;
TestServiceImplDupPkg dup_service;
SetUpServer(&service, &dup_service, nullptr);
ResetStub();
- std::thread response_stream_handler_thread(
- [this, &service] { HandleServerStreaming(&service, cqs_[0].get()); });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread response_stream_handler_thread(HandleServerStreaming<SType>,
+ &service, cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
TestAllMethods();
SendEchoToDupService();
response_stream_handler_thread.join();
@@ -413,18 +417,20 @@ TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_SyncDupService) {
// Add a second service with one async method.
TEST_F(HybridEnd2endTest, AsyncRequestStreamResponseStream_AsyncDupService) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>
+ SType;
+ SType service;
duplicate::EchoTestService::AsyncService dup_service;
SetUpServer(&service, &dup_service, nullptr);
ResetStub();
- std::thread response_stream_handler_thread(
- [this, &service] { HandleServerStreaming(&service, cqs_[0].get()); });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread response_stream_handler_thread(HandleServerStreaming<SType>,
+ &service, cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
std::thread echo_handler_thread(
- [this, &dup_service] { HandleEcho(&dup_service, cqs_[2].get(), true); });
+ HandleEcho<duplicate::EchoTestService::AsyncService>, &dup_service,
+ cqs_[2].get(), true);
TestAllMethods();
SendEchoToDupService();
response_stream_handler_thread.join();
@@ -437,25 +443,24 @@ TEST_F(HybridEnd2endTest, GenericEcho) {
AsyncGenericService generic_service;
SetUpServer(&service, nullptr, &generic_service);
ResetStub();
- std::thread generic_handler_thread([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[0].get());
- });
+ std::thread generic_handler_thread(HandleGenericCall, &generic_service,
+ cqs_[0].get());
TestAllMethods();
generic_handler_thread.join();
}
TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithGenericMethod_Echo<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithGenericMethod_Echo<TestServiceImpl>>
+ SType;
+ SType service;
AsyncGenericService generic_service;
SetUpServer(&service, nullptr, &generic_service);
ResetStub();
- std::thread generic_handler_thread([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[0].get());
- });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread generic_handler_thread(HandleGenericCall, &generic_service,
+ cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
TestAllMethods();
generic_handler_thread.join();
request_stream_handler_thread.join();
@@ -463,18 +468,18 @@ TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream) {
// Add a second service with one sync method.
TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_SyncDupService) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithGenericMethod_Echo<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithGenericMethod_Echo<TestServiceImpl>>
+ SType;
+ SType service;
AsyncGenericService generic_service;
TestServiceImplDupPkg dup_service;
SetUpServer(&service, &dup_service, &generic_service);
ResetStub();
- std::thread generic_handler_thread([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[0].get());
- });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread generic_handler_thread(HandleGenericCall, &generic_service,
+ cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
TestAllMethods();
SendEchoToDupService();
generic_handler_thread.join();
@@ -483,20 +488,21 @@ TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_SyncDupService) {
// Add a second service with one async method.
TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_AsyncDupService) {
- EchoTestService::WithAsyncMethod_RequestStream<
- EchoTestService::WithGenericMethod_Echo<TestServiceImpl> >
- service;
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
+ EchoTestService::WithGenericMethod_Echo<TestServiceImpl>>
+ SType;
+ SType service;
AsyncGenericService generic_service;
duplicate::EchoTestService::AsyncService dup_service;
SetUpServer(&service, &dup_service, &generic_service);
ResetStub();
- std::thread generic_handler_thread([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[0].get());
- });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
+ std::thread generic_handler_thread(HandleGenericCall, &generic_service,
+ cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
std::thread echo_handler_thread(
- [this, &dup_service] { HandleEcho(&dup_service, cqs_[2].get(), true); });
+ HandleEcho<duplicate::EchoTestService::AsyncService>, &dup_service,
+ cqs_[2].get(), true);
TestAllMethods();
SendEchoToDupService();
generic_handler_thread.join();
@@ -505,20 +511,20 @@ TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStream_AsyncDupService) {
}
TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStreamResponseStream) {
- EchoTestService::WithAsyncMethod_RequestStream<
+ typedef EchoTestService::WithAsyncMethod_RequestStream<
EchoTestService::WithGenericMethod_Echo<
- EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl> > >
- service;
+ EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>>
+ SType;
+ SType service;
AsyncGenericService generic_service;
SetUpServer(&service, nullptr, &generic_service);
ResetStub();
- std::thread generic_handler_thread([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[0].get());
- });
- std::thread request_stream_handler_thread(
- [this, &service] { HandleClientStreaming(&service, cqs_[1].get()); });
- std::thread response_stream_handler_thread(
- [this, &service] { HandleServerStreaming(&service, cqs_[2].get()); });
+ std::thread generic_handler_thread(HandleGenericCall, &generic_service,
+ cqs_[0].get());
+ std::thread request_stream_handler_thread(HandleClientStreaming<SType>,
+ &service, cqs_[1].get());
+ std::thread response_stream_handler_thread(HandleServerStreaming<SType>,
+ &service, cqs_[2].get());
TestAllMethods();
generic_handler_thread.join();
request_stream_handler_thread.join();
@@ -526,21 +532,20 @@ TEST_F(HybridEnd2endTest, GenericEchoAsyncRequestStreamResponseStream) {
}
TEST_F(HybridEnd2endTest, GenericEchoRequestStreamAsyncResponseStream) {
- EchoTestService::WithGenericMethod_RequestStream<
+ typedef EchoTestService::WithGenericMethod_RequestStream<
EchoTestService::WithGenericMethod_Echo<
- EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl> > >
- service;
+ EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>>
+ SType;
+ SType service;
AsyncGenericService generic_service;
SetUpServer(&service, nullptr, &generic_service);
ResetStub();
- std::thread generic_handler_thread([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[0].get());
- });
- std::thread generic_handler_thread2([this, &generic_service] {
- HandleGenericCall(&generic_service, cqs_[1].get());
- });
- std::thread response_stream_handler_thread(
- [this, &service] { HandleServerStreaming(&service, cqs_[2].get()); });
+ std::thread generic_handler_thread(HandleGenericCall, &generic_service,
+ cqs_[0].get());
+ std::thread generic_handler_thread2(HandleGenericCall, &generic_service,
+ cqs_[1].get());
+ std::thread response_stream_handler_thread(HandleServerStreaming<SType>,
+ &service, cqs_[2].get());
TestAllMethods();
generic_handler_thread.join();
generic_handler_thread2.join();
@@ -552,7 +557,7 @@ TEST_F(HybridEnd2endTest, GenericEchoRequestStreamAsyncResponseStream) {
TEST_F(HybridEnd2endTest, GenericMethodWithoutGenericService) {
EchoTestService::WithGenericMethod_RequestStream<
EchoTestService::WithGenericMethod_Echo<
- EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl> > >
+ EchoTestService::WithAsyncMethod_ResponseStream<TestServiceImpl>>>
service;
SetUpServer(&service, nullptr, nullptr);
EXPECT_EQ(nullptr, server_.get());
diff --git a/test/cpp/end2end/proto_server_reflection_test.cc b/test/cpp/end2end/proto_server_reflection_test.cc
new file mode 100644
index 0000000000..f8fc39b553
--- /dev/null
+++ b/test/cpp/end2end/proto_server_reflection_test.cc
@@ -0,0 +1,166 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <google/protobuf/descriptor.h>
+#include <grpc++/channel.h>
+#include <grpc++/client_context.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/ext/proto_server_reflection_plugin.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/security/server_credentials.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc++/server_context.h>
+#include <grpc/grpc.h>
+#include <gtest/gtest.h>
+
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/end2end/test_service_impl.h"
+#include "test/cpp/util/proto_reflection_descriptor_database.h"
+
+namespace grpc {
+namespace testing {
+
+class ProtoServerReflectionTest : public ::testing::Test {
+ public:
+ ProtoServerReflectionTest() {}
+
+ void SetUp() GRPC_OVERRIDE {
+ port_ = grpc_pick_unused_port_or_die();
+ ref_desc_pool_ = google::protobuf::DescriptorPool::generated_pool();
+
+ ServerBuilder builder;
+ grpc::string server_address = "localhost:" + to_string(port_);
+ builder.AddListeningPort(server_address, InsecureServerCredentials());
+ server_ = builder.BuildAndStart();
+ }
+
+ void ResetStub() {
+ string target = "dns:localhost:" + to_string(port_);
+ std::shared_ptr<Channel> channel =
+ CreateChannel(target, InsecureChannelCredentials());
+ stub_ = grpc::testing::EchoTestService::NewStub(channel);
+ desc_db_.reset(new ProtoReflectionDescriptorDatabase(channel));
+ desc_pool_.reset(new google::protobuf::DescriptorPool(desc_db_.get()));
+ }
+
+ string to_string(const int number) {
+ std::stringstream strs;
+ strs << number;
+ return strs.str();
+ }
+
+ void CompareService(const grpc::string& service) {
+ const google::protobuf::ServiceDescriptor* service_desc =
+ desc_pool_->FindServiceByName(service);
+ const google::protobuf::ServiceDescriptor* ref_service_desc =
+ ref_desc_pool_->FindServiceByName(service);
+ EXPECT_TRUE(service_desc != nullptr);
+ EXPECT_TRUE(ref_service_desc != nullptr);
+ EXPECT_EQ(service_desc->DebugString(), ref_service_desc->DebugString());
+
+ const google::protobuf::FileDescriptor* file_desc = service_desc->file();
+ if (known_files_.find(file_desc->package() + "/" + file_desc->name()) !=
+ known_files_.end()) {
+ EXPECT_EQ(file_desc->DebugString(),
+ ref_service_desc->file()->DebugString());
+ known_files_.insert(file_desc->package() + "/" + file_desc->name());
+ }
+
+ for (int i = 0; i < service_desc->method_count(); ++i) {
+ CompareMethod(service_desc->method(i)->full_name());
+ }
+ }
+
+ void CompareMethod(const grpc::string& method) {
+ const google::protobuf::MethodDescriptor* method_desc =
+ desc_pool_->FindMethodByName(method);
+ const google::protobuf::MethodDescriptor* ref_method_desc =
+ ref_desc_pool_->FindMethodByName(method);
+ EXPECT_TRUE(method_desc != nullptr);
+ EXPECT_TRUE(ref_method_desc != nullptr);
+ EXPECT_EQ(method_desc->DebugString(), ref_method_desc->DebugString());
+
+ CompareType(method_desc->input_type()->full_name());
+ CompareType(method_desc->output_type()->full_name());
+ }
+
+ void CompareType(const grpc::string& type) {
+ if (known_types_.find(type) != known_types_.end()) {
+ return;
+ }
+
+ const google::protobuf::Descriptor* desc =
+ desc_pool_->FindMessageTypeByName(type);
+ const google::protobuf::Descriptor* ref_desc =
+ ref_desc_pool_->FindMessageTypeByName(type);
+ EXPECT_TRUE(desc != nullptr);
+ EXPECT_TRUE(ref_desc != nullptr);
+ EXPECT_EQ(desc->DebugString(), ref_desc->DebugString());
+ }
+
+ protected:
+ std::unique_ptr<Server> server_;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+ std::unique_ptr<ProtoReflectionDescriptorDatabase> desc_db_;
+ std::unique_ptr<google::protobuf::DescriptorPool> desc_pool_;
+ std::unordered_set<string> known_files_;
+ std::unordered_set<string> known_types_;
+ const google::protobuf::DescriptorPool* ref_desc_pool_;
+ int port_;
+ reflection::ProtoServerReflectionPlugin plugin_;
+};
+
+TEST_F(ProtoServerReflectionTest, CheckResponseWithLocalDescriptorPool) {
+ ResetStub();
+
+ std::vector<std::string> services;
+ desc_db_->GetServices(&services);
+ // The service list has at least one service (reflection servcie).
+ EXPECT_TRUE(services.size() > 0);
+
+ for (auto it = services.begin(); it != services.end(); ++it) {
+ CompareService(*it);
+ }
+}
+
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc
index 8a74621e5a..778a2be573 100644
--- a/test/cpp/end2end/server_builder_plugin_test.cc
+++ b/test/cpp/end2end/server_builder_plugin_test.cc
@@ -37,6 +37,7 @@
#include <grpc++/impl/server_builder_option.h>
#include <grpc++/impl/server_builder_plugin.h>
#include <grpc++/impl/server_initializer.h>
+#include <grpc++/impl/thd.h>
#include <grpc++/security/credentials.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server.h>
@@ -61,6 +62,7 @@ class TestServerBuilderPlugin : public ServerBuilderPlugin {
init_server_is_called_ = false;
finish_is_called_ = false;
change_arguments_is_called_ = false;
+ register_service_ = false;
}
grpc::string name() GRPC_OVERRIDE { return PLUGIN_NAME; }
@@ -112,15 +114,14 @@ class InsertPluginServerBuilderOption : public ServerBuilderOption {
void UpdateArguments(ChannelArguments* arg) GRPC_OVERRIDE {}
- void UpdatePlugins(
- std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>>* plugins)
+ void UpdatePlugins(std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins)
GRPC_OVERRIDE {
plugins->clear();
std::unique_ptr<TestServerBuilderPlugin> plugin(
new TestServerBuilderPlugin());
if (register_service_) plugin->SetRegisterService();
- (*plugins)[plugin->name()] = std::move(plugin);
+ plugins->emplace_back(std::move(plugin));
}
void SetRegisterService() { register_service_ = true; }
@@ -161,7 +162,7 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
void InsertPlugin() {
if (GetParam()) {
// Add ServerBuilder plugin in static initialization
- EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
+ CheckPresent();
} else {
// Add ServerBuilder plugin using ServerBuilder::SetOption()
builder_->SetOption(std::unique_ptr<ServerBuilderOption>(
@@ -172,10 +173,8 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
void InsertPluginWithTestService() {
if (GetParam()) {
// Add ServerBuilder plugin in static initialization
- EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
- auto plugin = static_cast<TestServerBuilderPlugin*>(
- builder_->plugins_[PLUGIN_NAME].get());
- EXPECT_TRUE(plugin != nullptr);
+ auto plugin = CheckPresent();
+ EXPECT_TRUE(plugin);
plugin->SetRegisterService();
} else {
// Add ServerBuilder plugin using ServerBuilder::SetOption()
@@ -189,9 +188,12 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
void StartServer() {
grpc::string server_address = "localhost:" + to_string(port_);
builder_->AddListeningPort(server_address, InsecureServerCredentials());
+ // we run some tests without a service, and for those we need to supply a
+ // frequently polled completion queue
cq_ = builder_->AddCompletionQueue();
+ cq_thread_ = grpc::thread(std::bind(&ServerBuilderPluginTest::RunCQ, this));
server_ = builder_->BuildAndStart();
- EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
+ EXPECT_TRUE(CheckPresent());
}
void ResetStub() {
@@ -201,18 +203,13 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
}
void TearDown() GRPC_OVERRIDE {
- EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
- auto plugin = static_cast<TestServerBuilderPlugin*>(
- builder_->plugins_[PLUGIN_NAME].get());
- EXPECT_TRUE(plugin != nullptr);
+ auto plugin = CheckPresent();
+ EXPECT_TRUE(plugin);
EXPECT_TRUE(plugin->init_server_is_called());
EXPECT_TRUE(plugin->finish_is_called());
server_->Shutdown();
- void* tag;
- bool ok;
cq_->Shutdown();
- while (cq_->Next(&tag, &ok))
- ;
+ cq_thread_.join();
}
string to_string(const int number) {
@@ -227,8 +224,29 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<ServerCompletionQueue> cq_;
std::unique_ptr<Server> server_;
+ grpc::thread cq_thread_;
TestServiceImpl service_;
int port_;
+
+ private:
+ TestServerBuilderPlugin* CheckPresent() {
+ auto it = builder_->plugins_.begin();
+ for (; it != builder_->plugins_.end(); it++) {
+ if ((*it)->name() == PLUGIN_NAME) break;
+ }
+ if (it != builder_->plugins_.end()) {
+ return static_cast<TestServerBuilderPlugin*>(it->get());
+ } else {
+ return nullptr;
+ }
+ }
+
+ void RunCQ() {
+ void* tag;
+ bool ok;
+ while (cq_->Next(&tag, &ok))
+ ;
+ }
};
TEST_P(ServerBuilderPluginTest, PluginWithoutServiceTest) {
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index cbaee92228..52abd80d69 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -33,6 +33,7 @@
#include "test/cpp/end2end/test_service_impl.h"
+#include <string>
#include <thread>
#include <grpc++/security/credentials.h>
@@ -253,7 +254,7 @@ Status TestServiceImpl::ResponseStream(ServerContext* context,
}
for (int i = 0; i < kNumResponseStreamsMsgs; i++) {
- response.set_message(request->message() + std::to_string(i));
+ response.set_message(request->message() + grpc::to_string(i));
writer->Write(response);
}
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index 94541f9a45..b021b34523 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -230,7 +230,7 @@ class CommonStressTestSyncServer : public CommonStressTest<TestServiceImpl> {
};
class CommonStressTestAsyncServer
- : public CommonStressTest<::grpc::testing::EchoTestService::AsyncService> {
+ : public CommonStressTest<grpc::testing::EchoTestService::AsyncService> {
public:
void SetUp() GRPC_OVERRIDE {
shutting_down_ = false;
@@ -394,7 +394,7 @@ class AsyncClientEnd2endTest : public ::testing::Test {
for (int i = 0; i < num_rpcs; ++i) {
AsyncClientCall* call = new AsyncClientCall;
EchoRequest request;
- request.set_message("Hello: " + std::to_string(i));
+ request.set_message("Hello: " + grpc::to_string(i));
call->response_reader =
common_.GetStub()->AsyncEcho(&call->context, request, &cq_);
call->response_reader->Finish(&call->response, &call->status,
diff --git a/test/cpp/end2end/zookeeper_test.cc b/test/cpp/end2end/zookeeper_test.cc
index 12853a1b98..fdc500e535 100644
--- a/test/cpp/end2end/zookeeper_test.cc
+++ b/test/cpp/end2end/zookeeper_test.cc
@@ -101,7 +101,7 @@ class ZookeeperTest : public ::testing::Test {
zookeeper_address_ = addr_str;
gpr_free(addr);
}
- gpr_log(GPR_DEBUG, zookeeper_address_.c_str());
+ gpr_log(GPR_DEBUG, "%s", zookeeper_address_.c_str());
// Connects to zookeeper server
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 7727824979..e8ae6ee572 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -40,7 +40,9 @@
#include <grpc++/client_context.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
#include "test/cpp/interop/client_helper.h"
#include "test/cpp/interop/interop_client.h"
#include "test/cpp/util/test_config.h"
@@ -52,30 +54,31 @@ DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
DEFINE_string(server_host_override, "foo.test.google.fr",
"Override the server host which is sent in HTTP header");
DEFINE_string(test_case, "large_unary",
- "Configure different test cases. Valid options are: "
- "empty_unary : empty (zero bytes) request and response; "
- "large_unary : single request and (large) response; "
- "large_compressed_unary : single request and compressed (large) "
- "response; "
- "client_streaming : request streaming with single response; "
- "server_streaming : single request with response streaming; "
+ "Configure different test cases. Valid options are:\n\n"
+ "all : all test cases;\n"
+ "cancel_after_begin : cancel stream after starting it;\n"
+ "cancel_after_first_response: cancel on first response;\n"
+ "client_compressed_streaming : compressed request streaming with "
+ "client_compressed_unary : single compressed request;\n"
+ "client_streaming : request streaming with single response;\n"
+ "compute_engine_creds: large_unary with compute engine auth;\n"
+ "custom_metadata: server will echo custom metadata;\n"
+ "empty_stream : bi-di stream with no request/response;\n"
+ "empty_unary : empty (zero bytes) request and response;\n"
+ "half_duplex : half-duplex streaming;\n"
+ "jwt_token_creds: large_unary with JWT token auth;\n"
+ "large_unary : single request and (large) response;\n"
+ "oauth2_auth_token: raw oauth2 access token auth;\n"
+ "per_rpc_creds: raw oauth2 access token on a single rpc;\n"
+ "ping_pong : full-duplex streaming;\n"
+ "response streaming;\n"
"server_compressed_streaming : single request with compressed "
- "response streaming; "
- "slow_consumer : single request with response; "
- " streaming with slow client consumer; "
- "half_duplex : half-duplex streaming; "
- "ping_pong : full-duplex streaming; "
- "cancel_after_begin : cancel stream after starting it; "
- "cancel_after_first_response: cancel on first response; "
- "timeout_on_sleeping_server: deadline exceeds on stream; "
- "empty_stream : bi-di stream with no request/response; "
- "compute_engine_creds: large_unary with compute engine auth; "
- "jwt_token_creds: large_unary with JWT token auth; "
- "oauth2_auth_token: raw oauth2 access token auth; "
- "per_rpc_creds: raw oauth2 access token on a single rpc; "
- "status_code_and_message: verify status code & message; "
- "custom_metadata: server will echo custom metadata;"
- "all : all of above.");
+ "server_compressed_unary : single compressed response;\n"
+ "server_streaming : single request with response streaming;\n"
+ "slow_consumer : single request with response streaming with "
+ "slow client consumer;\n"
+ "status_code_and_message: verify status code & message;\n"
+ "timeout_on_sleeping_server: deadline exceeds on stream;\n");
DEFINE_string(default_service_account, "",
"Email of GCE default service account");
DEFINE_string(service_account_key_file, "",
@@ -104,14 +107,18 @@ int main(int argc, char** argv) {
client.DoEmpty();
} else if (FLAGS_test_case == "large_unary") {
client.DoLargeUnary();
- } else if (FLAGS_test_case == "large_compressed_unary") {
- client.DoLargeCompressedUnary();
+ } else if (FLAGS_test_case == "server_compressed_unary") {
+ client.DoServerCompressedUnary();
+ } else if (FLAGS_test_case == "client_compressed_unary") {
+ client.DoClientCompressedUnary();
} else if (FLAGS_test_case == "client_streaming") {
client.DoRequestStreaming();
} else if (FLAGS_test_case == "server_streaming") {
client.DoResponseStreaming();
} else if (FLAGS_test_case == "server_compressed_streaming") {
- client.DoResponseCompressedStreaming();
+ client.DoServerCompressedStreaming();
+ } else if (FLAGS_test_case == "client_compressed_streaming") {
+ client.DoClientCompressedStreaming();
} else if (FLAGS_test_case == "slow_consumer") {
client.DoResponseStreamingWithSlowConsumer();
} else if (FLAGS_test_case == "half_duplex") {
@@ -144,9 +151,12 @@ int main(int argc, char** argv) {
} else if (FLAGS_test_case == "all") {
client.DoEmpty();
client.DoLargeUnary();
+ client.DoClientCompressedUnary();
+ client.DoServerCompressedUnary();
client.DoRequestStreaming();
client.DoResponseStreaming();
- client.DoResponseCompressedStreaming();
+ client.DoClientCompressedStreaming();
+ client.DoServerCompressedStreaming();
client.DoHalfDuplex();
client.DoPingPong();
client.DoCancelAfterBegin();
@@ -165,14 +175,35 @@ int main(int argc, char** argv) {
}
// compute_engine_creds only runs in GCE.
} else {
- gpr_log(
- GPR_ERROR,
- "Unsupported test case %s. Valid options are all|empty_unary|"
- "large_unary|large_compressed_unary|client_streaming|server_streaming|"
- "server_compressed_streaming|half_duplex|ping_pong|cancel_after_begin|"
- "cancel_after_first_response|timeout_on_sleeping_server|empty_stream|"
- "compute_engine_creds|jwt_token_creds|oauth2_auth_token|per_rpc_creds",
- "status_code_and_message|custom_metadata", FLAGS_test_case.c_str());
+ const char* testcases[] = {"all",
+ "cancel_after_begin",
+ "cancel_after_first_response",
+ "client_compressed_streaming",
+ "client_compressed_unary",
+ "client_streaming",
+ "compute_engine_creds",
+ "custom_metadata",
+ "empty_stream",
+ "empty_unary",
+ "half_duplex",
+ "jwt_token_creds",
+ "large_unary",
+ "oauth2_auth_token",
+ "oauth2_auth_token",
+ "per_rpc_creds",
+ "per_rpc_creds",
+ "ping_pong",
+ "server_compressed_streaming",
+ "server_compressed_unary",
+ "server_streaming",
+ "status_code_and_message",
+ "timeout_on_sleeping_server"};
+ char* joined_testcases =
+ gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", NULL);
+
+ gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s",
+ FLAGS_test_case.c_str(), joined_testcases);
+ gpr_free(joined_testcases);
ret = 1;
}
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 189e4a8aab..8861bc1163 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,10 +31,8 @@
*
*/
-#include "test/cpp/interop/interop_client.h"
-
#include <unistd.h>
-
+#include <cinttypes>
#include <fstream>
#include <memory>
@@ -51,51 +49,41 @@
#include "src/proto/grpc/testing/messages.grpc.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/client_helper.h"
+#include "test/cpp/interop/interop_client.h"
namespace grpc {
namespace testing {
-static const char* kRandomFile = "test/cpp/interop/rnd.dat";
-
namespace {
// The same value is defined by the Java client.
const std::vector<int> request_stream_sizes = {27182, 8, 1828, 45904};
-const std::vector<int> response_stream_sizes = {31415, 59, 2653, 58979};
+const std::vector<int> response_stream_sizes = {31415, 9, 2653, 58979};
const int kNumResponseMessages = 2000;
const int kResponseMessageSize = 1030;
const int kReceiveDelayMilliSeconds = 20;
const int kLargeRequestSize = 271828;
const int kLargeResponseSize = 314159;
-CompressionType GetInteropCompressionTypeFromCompressionAlgorithm(
- grpc_compression_algorithm algorithm) {
- switch (algorithm) {
- case GRPC_COMPRESS_NONE:
- return CompressionType::NONE;
- case GRPC_COMPRESS_GZIP:
- return CompressionType::GZIP;
- case GRPC_COMPRESS_DEFLATE:
- return CompressionType::DEFLATE;
- default:
- GPR_ASSERT(false);
- }
-}
-
void NoopChecks(const InteropClientContextInspector& inspector,
const SimpleRequest* request, const SimpleResponse* response) {}
-void CompressionChecks(const InteropClientContextInspector& inspector,
- const SimpleRequest* request,
- const SimpleResponse* response) {
- GPR_ASSERT(request->response_compression() ==
- GetInteropCompressionTypeFromCompressionAlgorithm(
- inspector.GetCallCompressionAlgorithm()));
- if (request->response_compression() == NONE) {
- GPR_ASSERT(!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
- } else if (request->response_type() == PayloadType::COMPRESSABLE) {
- // requested compression and compressable response => results should always
- // be compressed.
+void UnaryCompressionChecks(const InteropClientContextInspector& inspector,
+ const SimpleRequest* request,
+ const SimpleResponse* response) {
+ const grpc_compression_algorithm received_compression =
+ inspector.GetCallCompressionAlgorithm();
+ if (request->response_compressed().value()) {
+ if (received_compression == GRPC_COMPRESS_NONE) {
+ // Requested some compression, got NONE. This is an error.
+ gpr_log(GPR_ERROR,
+ "Failure: Requested compression but got uncompressed response "
+ "from server.");
+ abort();
+ }
GPR_ASSERT(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS);
+ } else {
+ // Didn't request compression -> make sure the response is uncompressed
+ GPR_ASSERT(!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
}
}
} // namespace
@@ -197,11 +185,16 @@ bool InteropClient::PerformLargeUnary(SimpleRequest* request,
CheckerFn custom_checks_fn) {
ClientContext context;
InteropClientContextInspector inspector(context);
- // If the request doesn't already specify the response type, default to
- // COMPRESSABLE.
request->set_response_size(kLargeResponseSize);
grpc::string payload(kLargeRequestSize, '\0');
request->mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
+ if (request->has_expect_compressed()) {
+ if (request->expect_compressed().value()) {
+ context.set_compression_algorithm(GRPC_COMPRESS_GZIP);
+ } else {
+ context.set_compression_algorithm(GRPC_COMPRESS_NONE);
+ }
+ }
Status s = serviceStub_.Get()->UnaryCall(&context, *request, response);
if (!AssertStatusOk(s)) {
@@ -211,25 +204,8 @@ bool InteropClient::PerformLargeUnary(SimpleRequest* request,
custom_checks_fn(inspector, request, response);
// Payload related checks.
- if (request->response_type() != PayloadType::RANDOM) {
- GPR_ASSERT(response->payload().type() == request->response_type());
- }
- switch (response->payload().type()) {
- case PayloadType::COMPRESSABLE:
- GPR_ASSERT(response->payload().body() ==
- grpc::string(kLargeResponseSize, '\0'));
- break;
- case PayloadType::UNCOMPRESSABLE: {
- std::ifstream rnd_file(kRandomFile);
- GPR_ASSERT(rnd_file.good());
- for (int i = 0; i < kLargeResponseSize; i++) {
- GPR_ASSERT(response->payload().body()[i] == (char)rnd_file.get());
- }
- } break;
- default:
- GPR_ASSERT(false);
- }
-
+ GPR_ASSERT(response->payload().body() ==
+ grpc::string(kLargeResponseSize, '\0'));
return true;
}
@@ -242,7 +218,6 @@ bool InteropClient::DoComputeEngineCreds(
SimpleResponse response;
request.set_fill_username(true);
request.set_fill_oauth_scope(true);
- request.set_response_type(PayloadType::COMPRESSABLE);
if (!PerformLargeUnary(&request, &response)) {
return false;
@@ -316,7 +291,6 @@ bool InteropClient::DoJwtTokenCreds(const grpc::string& username) {
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
- request.set_response_type(PayloadType::COMPRESSABLE);
if (!PerformLargeUnary(&request, &response)) {
return false;
@@ -332,7 +306,6 @@ bool InteropClient::DoLargeUnary() {
gpr_log(GPR_DEBUG, "Sending a large unary rpc...");
SimpleRequest request;
SimpleResponse response;
- request.set_response_type(PayloadType::COMPRESSABLE);
if (!PerformLargeUnary(&request, &response)) {
return false;
}
@@ -340,32 +313,73 @@ bool InteropClient::DoLargeUnary() {
return true;
}
-bool InteropClient::DoLargeCompressedUnary() {
- const CompressionType compression_types[] = {NONE, GZIP, DEFLATE};
- const PayloadType payload_types[] = {COMPRESSABLE, UNCOMPRESSABLE, RANDOM};
- for (size_t i = 0; i < GPR_ARRAY_SIZE(payload_types); i++) {
- for (size_t j = 0; j < GPR_ARRAY_SIZE(compression_types); j++) {
- char* log_suffix;
- gpr_asprintf(&log_suffix, "(compression=%s; payload=%s)",
- CompressionType_Name(compression_types[j]).c_str(),
- PayloadType_Name(payload_types[i]).c_str());
-
- gpr_log(GPR_DEBUG, "Sending a large compressed unary rpc %s.",
- log_suffix);
- SimpleRequest request;
- SimpleResponse response;
- request.set_response_type(payload_types[i]);
- request.set_response_compression(compression_types[j]);
-
- if (!PerformLargeUnary(&request, &response, CompressionChecks)) {
- gpr_log(GPR_ERROR, "Large compressed unary failed %s", log_suffix);
- gpr_free(log_suffix);
- return false;
- }
-
- gpr_log(GPR_DEBUG, "Large compressed unary done %s.", log_suffix);
+bool InteropClient::DoClientCompressedUnary() {
+ // Probing for compression-checks support.
+ ClientContext probe_context;
+ SimpleRequest probe_req;
+ SimpleResponse probe_res;
+
+ probe_context.set_compression_algorithm(GRPC_COMPRESS_NONE);
+ probe_req.mutable_expect_compressed()->set_value(true); // lies!
+
+ probe_req.set_response_size(kLargeResponseSize);
+ probe_req.mutable_payload()->set_body(grpc::string(kLargeRequestSize, '\0'));
+
+ gpr_log(GPR_DEBUG, "Sending probe for compressed unary request.");
+ const Status s =
+ serviceStub_.Get()->UnaryCall(&probe_context, probe_req, &probe_res);
+ if (s.error_code() != grpc::StatusCode::INVALID_ARGUMENT) {
+ // The server isn't able to evaluate incoming compression, making the rest
+ // of this test moot.
+ gpr_log(GPR_DEBUG, "Compressed unary request probe failed");
+ return false;
+ }
+ gpr_log(GPR_DEBUG, "Compressed unary request probe succeeded. Proceeding.");
+
+ const std::vector<bool> compressions = {true, false};
+ for (size_t i = 0; i < compressions.size(); i++) {
+ char* log_suffix;
+ gpr_asprintf(&log_suffix, "(compression=%s)",
+ compressions[i] ? "true" : "false");
+
+ gpr_log(GPR_DEBUG, "Sending compressed unary request %s.", log_suffix);
+ SimpleRequest request;
+ SimpleResponse response;
+ request.mutable_expect_compressed()->set_value(compressions[i]);
+ if (!PerformLargeUnary(&request, &response, UnaryCompressionChecks)) {
+ gpr_log(GPR_ERROR, "Compressed unary request failed %s", log_suffix);
gpr_free(log_suffix);
+ return false;
}
+
+ gpr_log(GPR_DEBUG, "Compressed unary request failed %s", log_suffix);
+ gpr_free(log_suffix);
+ }
+
+ return true;
+}
+
+bool InteropClient::DoServerCompressedUnary() {
+ const std::vector<bool> compressions = {true, false};
+ for (size_t i = 0; i < compressions.size(); i++) {
+ char* log_suffix;
+ gpr_asprintf(&log_suffix, "(compression=%s)",
+ compressions[i] ? "true" : "false");
+
+ gpr_log(GPR_DEBUG, "Sending unary request for compressed response %s.",
+ log_suffix);
+ SimpleRequest request;
+ SimpleResponse response;
+ request.mutable_response_compressed()->set_value(compressions[i]);
+
+ if (!PerformLargeUnary(&request, &response, UnaryCompressionChecks)) {
+ gpr_log(GPR_ERROR, "Request for compressed unary failed %s", log_suffix);
+ gpr_free(log_suffix);
+ return false;
+ }
+
+ gpr_log(GPR_DEBUG, "Request for compressed unary failed %s", log_suffix);
+ gpr_free(log_suffix);
}
return true;
@@ -392,7 +406,7 @@ bool InteropClient::DoRequestStreaming() {
serviceStub_.Get()->StreamingInputCall(&context, &response));
int aggregated_payload_size = 0;
- for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
+ for (size_t i = 0; i < request_stream_sizes.size(); ++i) {
Payload* payload = request.mutable_payload();
payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
if (!stream->Write(request)) {
@@ -401,7 +415,7 @@ bool InteropClient::DoRequestStreaming() {
}
aggregated_payload_size += request_stream_sizes[i];
}
- stream->WritesDone();
+ GPR_ASSERT(stream->WritesDone());
Status s = stream->Finish();
if (!AssertStatusOk(s)) {
@@ -437,7 +451,7 @@ bool InteropClient::DoResponseStreaming() {
// most likely due to connection failure.
gpr_log(GPR_ERROR,
"DoResponseStreaming(): Read fewer streams (%d) than "
- "response_stream_sizes.size() (%d)",
+ "response_stream_sizes.size() (%" PRIuPTR ")",
i, response_stream_sizes.size());
return TransientFailureOrAbort();
}
@@ -451,95 +465,128 @@ bool InteropClient::DoResponseStreaming() {
return true;
}
-bool InteropClient::DoResponseCompressedStreaming() {
- const CompressionType compression_types[] = {NONE, GZIP, DEFLATE};
- const PayloadType payload_types[] = {COMPRESSABLE, UNCOMPRESSABLE, RANDOM};
- for (size_t i = 0; i < GPR_ARRAY_SIZE(payload_types); i++) {
- for (size_t j = 0; j < GPR_ARRAY_SIZE(compression_types); j++) {
- ClientContext context;
- InteropClientContextInspector inspector(context);
- StreamingOutputCallRequest request;
-
- char* log_suffix;
- gpr_asprintf(&log_suffix, "(compression=%s; payload=%s)",
- CompressionType_Name(compression_types[j]).c_str(),
- PayloadType_Name(payload_types[i]).c_str());
-
- gpr_log(GPR_DEBUG, "Receiving response streaming rpc %s.", log_suffix);
-
- request.set_response_type(payload_types[i]);
- request.set_response_compression(compression_types[j]);
-
- for (size_t k = 0; k < response_stream_sizes.size(); ++k) {
- ResponseParameters* response_parameter =
- request.add_response_parameters();
- response_parameter->set_size(response_stream_sizes[k]);
- }
- StreamingOutputCallResponse response;
-
- std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
- serviceStub_.Get()->StreamingOutputCall(&context, request));
-
- size_t k = 0;
- while (stream->Read(&response)) {
- // Payload related checks.
- if (request.response_type() != PayloadType::RANDOM) {
- GPR_ASSERT(response.payload().type() == request.response_type());
- }
- switch (response.payload().type()) {
- case PayloadType::COMPRESSABLE:
- GPR_ASSERT(response.payload().body() ==
- grpc::string(response_stream_sizes[k], '\0'));
- break;
- case PayloadType::UNCOMPRESSABLE: {
- std::ifstream rnd_file(kRandomFile);
- GPR_ASSERT(rnd_file.good());
- for (int n = 0; n < response_stream_sizes[k]; n++) {
- GPR_ASSERT(response.payload().body()[n] == (char)rnd_file.get());
- }
- } break;
- default:
- GPR_ASSERT(false);
- }
-
- // Compression related checks.
- GPR_ASSERT(request.response_compression() ==
- GetInteropCompressionTypeFromCompressionAlgorithm(
- inspector.GetCallCompressionAlgorithm()));
- if (request.response_compression() == NONE) {
- GPR_ASSERT(
- !(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
- } else if (request.response_type() == PayloadType::COMPRESSABLE) {
- // requested compression and compressable response => results should
- // always be compressed.
- GPR_ASSERT(inspector.GetMessageFlags() &
- GRPC_WRITE_INTERNAL_COMPRESS);
- }
-
- ++k;
- }
-
- gpr_log(GPR_DEBUG, "Response streaming done %s.", log_suffix);
- gpr_free(log_suffix);
+bool InteropClient::DoClientCompressedStreaming() {
+ // Probing for compression-checks support.
+ ClientContext probe_context;
+ StreamingInputCallRequest probe_req;
+ StreamingInputCallResponse probe_res;
+
+ probe_context.set_compression_algorithm(GRPC_COMPRESS_NONE);
+ probe_req.mutable_expect_compressed()->set_value(true); // lies!
+ probe_req.mutable_payload()->set_body(grpc::string(27182, '\0'));
+
+ gpr_log(GPR_DEBUG, "Sending probe for compressed streaming request.");
- if (k < response_stream_sizes.size()) {
- // stream->Read() failed before reading all the expected messages. This
- // is most likely due to a connection failure.
- gpr_log(GPR_ERROR,
- "DoResponseCompressedStreaming(): Responses read (k=%d) is "
- "less than the expected messages (i.e "
- "response_stream_sizes.size() (%d)). (i=%d, j=%d)",
- k, response_stream_sizes.size(), i, j);
- return TransientFailureOrAbort();
- }
-
- Status s = stream->Finish();
- if (!AssertStatusOk(s)) {
- return false;
- }
+ std::unique_ptr<ClientWriter<StreamingInputCallRequest>> probe_stream(
+ serviceStub_.Get()->StreamingInputCall(&probe_context, &probe_res));
+
+ if (!probe_stream->Write(probe_req)) {
+ gpr_log(GPR_ERROR, "%s(): stream->Write() failed", __func__);
+ return TransientFailureOrAbort();
+ }
+ Status s = probe_stream->Finish();
+ if (s.error_code() != grpc::StatusCode::INVALID_ARGUMENT) {
+ // The server isn't able to evaluate incoming compression, making the rest
+ // of this test moot.
+ gpr_log(GPR_DEBUG, "Compressed streaming request probe failed");
+ return false;
+ }
+ gpr_log(GPR_DEBUG,
+ "Compressed streaming request probe succeeded. Proceeding.");
+
+ ClientContext context;
+ StreamingInputCallRequest request;
+ StreamingInputCallResponse response;
+
+ context.set_compression_algorithm(GRPC_COMPRESS_GZIP);
+ std::unique_ptr<ClientWriter<StreamingInputCallRequest>> stream(
+ serviceStub_.Get()->StreamingInputCall(&context, &response));
+
+ request.mutable_payload()->set_body(grpc::string(27182, '\0'));
+ request.mutable_expect_compressed()->set_value(true);
+ gpr_log(GPR_DEBUG, "Sending streaming request with compression enabled");
+ if (!stream->Write(request)) {
+ gpr_log(GPR_ERROR, "%s(): stream->Write() failed", __func__);
+ return TransientFailureOrAbort();
+ }
+
+ WriteOptions wopts;
+ wopts.set_no_compression();
+ request.mutable_payload()->set_body(grpc::string(45904, '\0'));
+ request.mutable_expect_compressed()->set_value(false);
+ gpr_log(GPR_DEBUG, "Sending streaming request with compression disabled");
+ if (!stream->Write(request, wopts)) {
+ gpr_log(GPR_ERROR, "%s(): stream->Write() failed", __func__);
+ return TransientFailureOrAbort();
+ }
+ GPR_ASSERT(stream->WritesDone());
+
+ s = stream->Finish();
+ if (!AssertStatusOk(s)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool InteropClient::DoServerCompressedStreaming() {
+ const std::vector<bool> compressions = {true, false};
+ const std::vector<int> sizes = {31415, 92653};
+
+ ClientContext context;
+ InteropClientContextInspector inspector(context);
+ StreamingOutputCallRequest request;
+
+ GPR_ASSERT(compressions.size() == sizes.size());
+ for (size_t i = 0; i < sizes.size(); i++) {
+ char* log_suffix;
+ gpr_asprintf(&log_suffix, "(compression=%s; size=%d)",
+ compressions[i] ? "true" : "false", sizes[i]);
+
+ gpr_log(GPR_DEBUG, "Sending request streaming rpc %s.", log_suffix);
+ gpr_free(log_suffix);
+
+ ResponseParameters* const response_parameter =
+ request.add_response_parameters();
+ response_parameter->mutable_compressed()->set_value(compressions[i]);
+ response_parameter->set_size(sizes[i]);
+ }
+ std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
+ serviceStub_.Get()->StreamingOutputCall(&context, request));
+
+ size_t k = 0;
+ StreamingOutputCallResponse response;
+ while (stream->Read(&response)) {
+ // Payload size checks.
+ GPR_ASSERT(response.payload().body() ==
+ grpc::string(request.response_parameters(k).size(), '\0'));
+
+ // Compression checks.
+ GPR_ASSERT(request.response_parameters(k).has_compressed());
+ if (request.response_parameters(k).compressed().value()) {
+ GPR_ASSERT(inspector.GetCallCompressionAlgorithm() > GRPC_COMPRESS_NONE);
+ GPR_ASSERT(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS);
+ } else {
+ // requested *no* compression.
+ GPR_ASSERT(!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
}
+ ++k;
}
+ if (k < sizes.size()) {
+ // stream->Read() failed before reading all the expected messages. This
+ // is most likely due to a connection failure.
+ gpr_log(GPR_ERROR,
+ "%s(): Responses read (k=%" PRIuPTR
+ ") is less than the expected number of messages (%" PRIuPTR ").",
+ __func__, k, sizes.size());
+ return TransientFailureOrAbort();
+ }
+
+ Status s = stream->Finish();
+ if (!AssertStatusOk(s)) {
+ return false;
+ }
return true;
}
@@ -617,7 +664,7 @@ bool InteropClient::DoHalfDuplex() {
// most likely due to a connection failure
gpr_log(GPR_ERROR,
"DoHalfDuplex(): Responses read (i=%d) are less than the expected "
- "number of messages response_stream_sizes.size() (%d)",
+ "number of messages response_stream_sizes.size() (%" PRIuPTR ")",
i, response_stream_sizes.size());
return TransientFailureOrAbort();
}
@@ -640,7 +687,6 @@ bool InteropClient::DoPingPong() {
stream(serviceStub_.Get()->FullDuplexCall(&context));
StreamingOutputCallRequest request;
- request.set_response_type(PayloadType::COMPRESSABLE);
ResponseParameters* response_parameter = request.add_response_parameters();
Payload* payload = request.mutable_payload();
StreamingOutputCallResponse response;
@@ -707,7 +753,6 @@ bool InteropClient::DoCancelAfterFirstResponse() {
stream(serviceStub_.Get()->FullDuplexCall(&context));
StreamingOutputCallRequest request;
- request.set_response_type(PayloadType::COMPRESSABLE);
ResponseParameters* response_parameter = request.add_response_parameters();
response_parameter->set_size(31415);
request.mutable_payload()->set_body(grpc::string(27182, '\0'));
@@ -847,7 +892,6 @@ bool InteropClient::DoCustomMetadata() {
stream(serviceStub_.Get()->FullDuplexCall(&context));
StreamingOutputCallRequest request;
- request.set_response_type(PayloadType::COMPRESSABLE);
ResponseParameters* response_parameter = request.add_response_parameters();
response_parameter->set_size(kLargeResponseSize);
grpc::string payload(kLargeRequestSize, '\0');
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index ae75762bb8..eb886fcb7e 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -45,9 +45,9 @@ namespace grpc {
namespace testing {
// Function pointer for custom checks.
-using CheckerFn =
- std::function<void(const InteropClientContextInspector&,
- const SimpleRequest*, const SimpleResponse*)>;
+typedef std::function<void(const InteropClientContextInspector&,
+ const SimpleRequest*, const SimpleResponse*)>
+ CheckerFn;
class InteropClient {
public:
@@ -64,12 +64,14 @@ class InteropClient {
bool DoEmpty();
bool DoLargeUnary();
- bool DoLargeCompressedUnary();
+ bool DoServerCompressedUnary();
+ bool DoClientCompressedUnary();
bool DoPingPong();
bool DoHalfDuplex();
bool DoRequestStreaming();
bool DoResponseStreaming();
- bool DoResponseCompressedStreaming();
+ bool DoServerCompressedStreaming();
+ bool DoClientCompressedStreaming();
bool DoResponseStreamingWithSlowConsumer();
bool DoCancelAfterBegin();
bool DoCancelAfterFirstResponse();
diff --git a/test/cpp/interop/server_main.cc b/test/cpp/interop/interop_server.cc
index 889874fe49..ebef0002a3 100644
--- a/test/cpp/interop/server_main.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,7 @@
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/transport/byte_stream.h"
#include "src/proto/grpc/testing/empty.grpc.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
@@ -64,10 +65,10 @@ using grpc::ServerCredentials;
using grpc::ServerReader;
using grpc::ServerReaderWriter;
using grpc::ServerWriter;
+using grpc::WriteOptions;
using grpc::SslServerCredentialsOptions;
using grpc::testing::InteropServerContextInspector;
using grpc::testing::Payload;
-using grpc::testing::PayloadType;
using grpc::testing::SimpleRequest;
using grpc::testing::SimpleResponse;
using grpc::testing::StreamingInputCallRequest;
@@ -78,7 +79,6 @@ using grpc::testing::TestService;
using grpc::Status;
static bool got_sigint = false;
-static const char* kRandomFile = "test/cpp/interop/rnd.dat";
const char kEchoInitialMetadataKey[] = "x-grpc-test-echo-initial";
const char kEchoTrailingBinMetadataKey[] = "x-grpc-test-echo-trailing-bin";
@@ -110,50 +110,41 @@ void MaybeEchoMetadata(ServerContext* context) {
}
}
-bool SetPayload(PayloadType type, int size, Payload* payload) {
- PayloadType response_type;
- if (type == PayloadType::RANDOM) {
- response_type =
- rand() & 0x1 ? PayloadType::COMPRESSABLE : PayloadType::UNCOMPRESSABLE;
- } else {
- response_type = type;
- }
- payload->set_type(response_type);
- switch (response_type) {
- case PayloadType::COMPRESSABLE: {
- std::unique_ptr<char[]> body(new char[size]());
- payload->set_body(body.get(), size);
- } break;
- case PayloadType::UNCOMPRESSABLE: {
- std::unique_ptr<char[]> body(new char[size]());
- std::ifstream rnd_file(kRandomFile);
- GPR_ASSERT(rnd_file.good());
- rnd_file.read(body.get(), size);
- GPR_ASSERT(!rnd_file.eof()); // Requested more rnd bytes than available
- payload->set_body(body.get(), size);
- } break;
- default:
- GPR_ASSERT(false);
- }
+bool SetPayload(int size, Payload* payload) {
+ std::unique_ptr<char[]> body(new char[size]());
+ payload->set_body(body.get(), size);
return true;
}
-template <typename RequestType>
-void SetResponseCompression(ServerContext* context,
- const RequestType& request) {
- switch (request.response_compression()) {
- case grpc::testing::NONE:
- context->set_compression_algorithm(GRPC_COMPRESS_NONE);
- break;
- case grpc::testing::GZIP:
- context->set_compression_algorithm(GRPC_COMPRESS_GZIP);
- break;
- case grpc::testing::DEFLATE:
- context->set_compression_algorithm(GRPC_COMPRESS_DEFLATE);
- break;
- default:
- abort();
+bool CheckExpectedCompression(const ServerContext& context,
+ const bool compression_expected) {
+ const InteropServerContextInspector inspector(context);
+ const grpc_compression_algorithm received_compression =
+ inspector.GetCallCompressionAlgorithm();
+
+ if (compression_expected) {
+ if (received_compression == GRPC_COMPRESS_NONE) {
+ // Expected some compression, got NONE. This is an error.
+ gpr_log(GPR_ERROR,
+ "Expected compression but got uncompressed request from client.");
+ return false;
+ }
+ if (!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS)) {
+ gpr_log(GPR_ERROR,
+ "Failure: Requested compression in a compressable request, but "
+ "compression bit in message flags not set.");
+ return false;
+ }
+ } else {
+ // Didn't expect compression -> make sure the request is uncompressed
+ if (inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS) {
+ gpr_log(GPR_ERROR,
+ "Failure: Didn't requested compression, but compression bit in "
+ "message flags set.");
+ return false;
+ }
}
+ return true;
}
class TestServiceImpl : public TestService::Service {
@@ -167,11 +158,26 @@ class TestServiceImpl : public TestService::Service {
Status UnaryCall(ServerContext* context, const SimpleRequest* request,
SimpleResponse* response) {
MaybeEchoMetadata(context);
- SetResponseCompression(context, *request);
+ if (request->has_response_compressed()) {
+ const bool compression_requested = request->response_compressed().value();
+ gpr_log(GPR_DEBUG, "Request for compression (%s) present for %s",
+ compression_requested ? "enabled" : "disabled", __func__);
+ if (compression_requested) {
+ // Any level would do, let's go for HIGH because we are overachievers.
+ context->set_compression_level(GRPC_COMPRESS_LEVEL_HIGH);
+ } else {
+ context->set_compression_level(GRPC_COMPRESS_LEVEL_NONE);
+ }
+ }
+ if (!CheckExpectedCompression(*context,
+ request->expect_compressed().value())) {
+ return Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Compressed request expectation not met.");
+ }
if (request->response_size() > 0) {
- if (!SetPayload(request->response_type(), request->response_size(),
- response->mutable_payload())) {
- return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
+ if (!SetPayload(request->response_size(), response->mutable_payload())) {
+ return Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Error creating payload.");
}
}
@@ -187,17 +193,36 @@ class TestServiceImpl : public TestService::Service {
Status StreamingOutputCall(
ServerContext* context, const StreamingOutputCallRequest* request,
ServerWriter<StreamingOutputCallResponse>* writer) {
- SetResponseCompression(context, *request);
StreamingOutputCallResponse response;
bool write_success = true;
for (int i = 0; write_success && i < request->response_parameters_size();
i++) {
- if (!SetPayload(request->response_type(),
- request->response_parameters(i).size(),
+ if (!SetPayload(request->response_parameters(i).size(),
response.mutable_payload())) {
- return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
+ return Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Error creating payload.");
}
- write_success = writer->Write(response);
+ WriteOptions wopts;
+ if (request->response_parameters(i).has_compressed()) {
+ // Compress by default. Disabled on a per-message basis.
+ context->set_compression_level(GRPC_COMPRESS_LEVEL_HIGH);
+ const bool compression_requested =
+ request->response_parameters(i).compressed().value();
+ gpr_log(GPR_DEBUG, "Request for compression (%s) present for %s",
+ compression_requested ? "enabled" : "disabled", __func__);
+ if (!compression_requested) {
+ wopts.set_no_compression();
+ } // else, compression is already enabled via the context.
+ }
+ int time_us;
+ if ((time_us = request->response_parameters(i).interval_us()) > 0) {
+ // Sleep before response if needed
+ gpr_timespec sleep_time =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(time_us, GPR_TIMESPAN));
+ gpr_sleep_until(sleep_time);
+ }
+ write_success = writer->Write(response, wopts);
}
if (write_success) {
return Status::OK;
@@ -212,6 +237,11 @@ class TestServiceImpl : public TestService::Service {
StreamingInputCallRequest request;
int aggregated_payload_size = 0;
while (reader->Read(&request)) {
+ if (!CheckExpectedCompression(*context,
+ request.expect_compressed().value())) {
+ return Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Compressed request expectation not met.");
+ }
if (request.has_payload()) {
aggregated_payload_size += request.payload().body().size();
}
@@ -229,11 +259,18 @@ class TestServiceImpl : public TestService::Service {
StreamingOutputCallResponse response;
bool write_success = true;
while (write_success && stream->Read(&request)) {
- SetResponseCompression(context, request);
if (request.response_parameters_size() != 0) {
response.mutable_payload()->set_type(request.payload().type());
response.mutable_payload()->set_body(
grpc::string(request.response_parameters(0).size(), '\0'));
+ int time_us;
+ if ((time_us = request.response_parameters(0).interval_us()) > 0) {
+ // Sleep before response if needed
+ gpr_timespec sleep_time =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(time_us, GPR_TIMESPAN));
+ gpr_sleep_until(sleep_time);
+ }
write_success = stream->Write(response);
}
}
diff --git a/test/cpp/interop/metrics_client.cc b/test/cpp/interop/metrics_client.cc
index c8c2215fab..7a0cb994df 100644
--- a/test/cpp/interop/metrics_client.cc
+++ b/test/cpp/interop/metrics_client.cc
@@ -76,7 +76,7 @@ bool PrintMetrics(std::unique_ptr<MetricsService::Stub> stub, bool total_only,
while (reader->Read(&gauge_response)) {
if (gauge_response.value_case() == GaugeResponse::kLongValue) {
if (!total_only) {
- gpr_log(GPR_INFO, "%s: %ld", gauge_response.name().c_str(),
+ gpr_log(GPR_INFO, "%s: %lld", gauge_response.name().c_str(),
gauge_response.long_value());
}
overall_qps += gauge_response.long_value();
diff --git a/test/cpp/interop/rnd.dat b/test/cpp/interop/rnd.dat
deleted file mode 100644
index 8c7f38f9e0..0000000000
--- a/test/cpp/interop/rnd.dat
+++ /dev/null
Binary files differ
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index c6d891ad71..8b0b511bcb 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -72,6 +72,10 @@ uint32_t InteropServerContextInspector::GetEncodingsAcceptedByClient() const {
return grpc_call_test_only_get_encodings_accepted_by_peer(context_.call_);
}
+uint32_t InteropServerContextInspector::GetMessageFlags() const {
+ return grpc_call_test_only_get_message_flags(context_.call_);
+}
+
std::shared_ptr<const AuthContext>
InteropServerContextInspector::GetAuthContext() const {
return context_.auth_context();
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index 12865e4032..a1da14a4c8 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -54,6 +54,7 @@ class InteropServerContextInspector {
bool IsCancelled() const;
grpc_compression_algorithm GetCallCompressionAlgorithm() const;
uint32_t GetEncodingsAcceptedByClient() const;
+ uint32_t GetMessageFlags() const;
private:
const ::grpc::ServerContext& context_;
diff --git a/test/cpp/interop/stress_interop_client.cc b/test/cpp/interop/stress_interop_client.cc
index aa95682e74..1d5fc80cf2 100644
--- a/test/cpp/interop/stress_interop_client.cc
+++ b/test/cpp/interop/stress_interop_client.cc
@@ -138,8 +138,12 @@ bool StressTestInteropClient::RunTest(TestCaseType test_case) {
is_success = interop_client_->DoLargeUnary();
break;
}
- case LARGE_COMPRESSED_UNARY: {
- is_success = interop_client_->DoLargeCompressedUnary();
+ case CLIENT_COMPRESSED_UNARY: {
+ is_success = interop_client_->DoClientCompressedUnary();
+ break;
+ }
+ case CLIENT_COMPRESSED_STREAMING: {
+ is_success = interop_client_->DoClientCompressedStreaming();
break;
}
case CLIENT_STREAMING: {
@@ -150,8 +154,12 @@ bool StressTestInteropClient::RunTest(TestCaseType test_case) {
is_success = interop_client_->DoResponseStreaming();
break;
}
+ case SERVER_COMPRESSED_UNARY: {
+ is_success = interop_client_->DoServerCompressedUnary();
+ break;
+ }
case SERVER_COMPRESSED_STREAMING: {
- is_success = interop_client_->DoResponseCompressedStreaming();
+ is_success = interop_client_->DoServerCompressedStreaming();
break;
}
case SLOW_CONSUMER: {
diff --git a/test/cpp/interop/stress_interop_client.h b/test/cpp/interop/stress_interop_client.h
index aa93b58b4a..cf6a713473 100644
--- a/test/cpp/interop/stress_interop_client.h
+++ b/test/cpp/interop/stress_interop_client.h
@@ -51,29 +51,33 @@ using std::vector;
enum TestCaseType {
UNKNOWN_TEST = -1,
- EMPTY_UNARY = 0,
- LARGE_UNARY = 1,
- LARGE_COMPRESSED_UNARY = 2,
- CLIENT_STREAMING = 3,
- SERVER_STREAMING = 4,
- SERVER_COMPRESSED_STREAMING = 5,
- SLOW_CONSUMER = 6,
- HALF_DUPLEX = 7,
- PING_PONG = 8,
- CANCEL_AFTER_BEGIN = 9,
- CANCEL_AFTER_FIRST_RESPONSE = 10,
- TIMEOUT_ON_SLEEPING_SERVER = 11,
- EMPTY_STREAM = 12,
- STATUS_CODE_AND_MESSAGE = 13,
- CUSTOM_METADATA = 14
+ EMPTY_UNARY,
+ LARGE_UNARY,
+ CLIENT_COMPRESSED_UNARY,
+ CLIENT_COMPRESSED_STREAMING,
+ CLIENT_STREAMING,
+ SERVER_STREAMING,
+ SERVER_COMPRESSED_UNARY,
+ SERVER_COMPRESSED_STREAMING,
+ SLOW_CONSUMER,
+ HALF_DUPLEX,
+ PING_PONG,
+ CANCEL_AFTER_BEGIN,
+ CANCEL_AFTER_FIRST_RESPONSE,
+ TIMEOUT_ON_SLEEPING_SERVER,
+ EMPTY_STREAM,
+ STATUS_CODE_AND_MESSAGE,
+ CUSTOM_METADATA
};
const vector<pair<TestCaseType, grpc::string>> kTestCaseList = {
{EMPTY_UNARY, "empty_unary"},
{LARGE_UNARY, "large_unary"},
- {LARGE_COMPRESSED_UNARY, "large_compressed_unary"},
+ {CLIENT_COMPRESSED_UNARY, "client_compressed_unary"},
+ {CLIENT_COMPRESSED_STREAMING, "client_compressed_streaming"},
{CLIENT_STREAMING, "client_streaming"},
{SERVER_STREAMING, "server_streaming"},
+ {SERVER_COMPRESSED_UNARY, "server_compressed_unary"},
{SERVER_COMPRESSED_STREAMING, "server_compressed_streaming"},
{SLOW_CONSUMER, "slow_consumer"},
{HALF_DUPLEX, "half_duplex"},
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 2a89eb8018..047bd16408 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -125,13 +125,15 @@ class Client {
if (reset) {
Histogram* to_merge = new Histogram[threads_.size()];
for (size_t i = 0; i < threads_.size(); i++) {
- threads_[i]->Swap(&to_merge[i]);
- latencies.Merge(to_merge[i]);
+ threads_[i]->BeginSwap(&to_merge[i]);
}
- delete[] to_merge;
-
std::unique_ptr<UsageTimer> timer(new UsageTimer);
timer_.swap(timer);
+ for (size_t i = 0; i < threads_.size(); i++) {
+ threads_[i]->EndSwap();
+ latencies.Merge(to_merge[i]);
+ }
+ delete[] to_merge;
timer_result = timer->Mark();
} else {
// merge snapshots of each thread histogram
@@ -213,6 +215,7 @@ class Client {
public:
Thread(Client* client, size_t idx)
: done_(false),
+ new_stats_(nullptr),
client_(client),
idx_(idx),
impl_(&Thread::ThreadFunc, this) {}
@@ -225,9 +228,16 @@ class Client {
impl_.join();
}
- void Swap(Histogram* n) {
+ void BeginSwap(Histogram* n) {
std::lock_guard<std::mutex> g(mu_);
- n->Swap(&histogram_);
+ new_stats_ = n;
+ }
+
+ void EndSwap() {
+ std::unique_lock<std::mutex> g(mu_);
+ while (new_stats_ != nullptr) {
+ cv_.wait(g);
+ };
}
void MergeStatsInto(Histogram* hist) {
@@ -241,11 +251,10 @@ class Client {
void ThreadFunc() {
for (;;) {
- // lock since the thread should only be doing one thing at a time
- std::lock_guard<std::mutex> g(mu_);
// run the loop body
const bool thread_still_ok = client_->ThreadFunc(&histogram_, idx_);
- // see if we're done
+ // lock, see if we're done
+ std::lock_guard<std::mutex> g(mu_);
if (!thread_still_ok) {
gpr_log(GPR_ERROR, "Finishing client thread due to RPC error");
done_ = true;
@@ -253,11 +262,19 @@ class Client {
if (done_) {
return;
}
+ // check if we're resetting stats, swap out the histogram if so
+ if (new_stats_) {
+ new_stats_->Swap(&histogram_);
+ new_stats_ = nullptr;
+ cv_.notify_one();
+ }
}
}
std::mutex mu_;
+ std::condition_variable cv_;
bool done_;
+ Histogram* new_stats_;
Histogram histogram_;
Client* client_;
const size_t idx_;
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index c32160a7d4..1507d1e3d6 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -42,7 +42,6 @@
#include <thread>
#include <vector>
-#include <gflags/gflags.h>
#include <grpc++/alarm.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
@@ -181,14 +180,14 @@ class AsyncClient : public ClientImpl<StubType, RequestType> {
using namespace std::placeholders;
int t = 0;
- for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) {
- for (int ch = 0; ch < config.client_channels(); ch++) {
+ for (int ch = 0; ch < config.client_channels(); ch++) {
+ for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) {
auto* cq = cli_cqs_[t].get();
auto ctx =
setup_ctx(channels_[ch].get_stub(), next_issuers_[t], request_);
ctx->Start(cq);
- t = (t + 1) % cli_cqs_.size();
}
+ t = (t + 1) % cli_cqs_.size();
}
}
virtual ~AsyncClient() {
@@ -250,7 +249,8 @@ class AsyncUnaryClient GRPC_FINAL
: public AsyncClient<BenchmarkService::Stub, SimpleRequest> {
public:
explicit AsyncUnaryClient(const ClientConfig& config)
- : AsyncClient(config, SetupCtx, BenchmarkStubCreator) {
+ : AsyncClient<BenchmarkService::Stub, SimpleRequest>(
+ config, SetupCtx, BenchmarkStubCreator) {
StartThreads(num_async_threads_);
}
~AsyncUnaryClient() GRPC_OVERRIDE { EndThreads(); }
@@ -377,7 +377,8 @@ class AsyncStreamingClient GRPC_FINAL
: public AsyncClient<BenchmarkService::Stub, SimpleRequest> {
public:
explicit AsyncStreamingClient(const ClientConfig& config)
- : AsyncClient(config, SetupCtx, BenchmarkStubCreator) {
+ : AsyncClient<BenchmarkService::Stub, SimpleRequest>(
+ config, SetupCtx, BenchmarkStubCreator) {
StartThreads(num_async_threads_);
}
@@ -512,7 +513,8 @@ class GenericAsyncStreamingClient GRPC_FINAL
: public AsyncClient<grpc::GenericStub, ByteBuffer> {
public:
explicit GenericAsyncStreamingClient(const ClientConfig& config)
- : AsyncClient(config, SetupCtx, GenericStubCreator) {
+ : AsyncClient<grpc::GenericStub, ByteBuffer>(config, SetupCtx,
+ GenericStubCreator) {
StartThreads(num_async_threads_);
}
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index fb161f70ee..c88e95b80e 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -40,7 +40,6 @@
#include <thread>
#include <vector>
-#include <gflags/gflags.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/server.h>
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index 04b2b453f9..08bf045883 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -31,6 +31,7 @@
*
*/
+#include <cinttypes>
#include <deque>
#include <list>
#include <thread>
@@ -43,7 +44,6 @@
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
-#include <gtest/gtest.h>
#include "src/core/lib/support/env.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
@@ -245,8 +245,8 @@ std::unique_ptr<ScenarioResult> RunScenario(
// where class contained in std::vector must have a copy constructor
auto* servers = new ServerData[num_servers];
for (size_t i = 0; i < num_servers; i++) {
- gpr_log(GPR_INFO, "Starting server on %s (worker #%d)", workers[i].c_str(),
- i);
+ gpr_log(GPR_INFO, "Starting server on %s (worker #%" PRIuPTR ")",
+ workers[i].c_str(), i);
servers[i].stub = WorkerService::NewStub(
CreateChannel(workers[i], InsecureChannelCredentials()));
@@ -308,8 +308,8 @@ std::unique_ptr<ScenarioResult> RunScenario(
auto* clients = new ClientData[num_clients];
for (size_t i = 0; i < num_clients; i++) {
const auto& worker = workers[i + num_servers];
- gpr_log(GPR_INFO, "Starting client on %s (worker #%d)", worker.c_str(),
- i + num_servers);
+ gpr_log(GPR_INFO, "Starting client on %s (worker #%" PRIuPTR ")",
+ worker.c_str(), i + num_servers);
clients[i].stub = WorkerService::NewStub(
CreateChannel(worker, InsecureChannelCredentials()));
ClientConfig per_client_config = client_config;
diff --git a/test/cpp/qps/parse_json.cc b/test/cpp/qps/parse_json.cc
index df7a62f0a0..e4fc35fa41 100644
--- a/test/cpp/qps/parse_json.cc
+++ b/test/cpp/qps/parse_json.cc
@@ -31,8 +31,6 @@
*
*/
-#include <grpc++/support/config_protobuf.h>
-
#include "test/cpp/qps/parse_json.h"
#include <string>
@@ -57,11 +55,26 @@ void ParseJson(const grpc::string& json, const grpc::string& type,
grpc::string errmsg(status.error_message());
gpr_log(GPR_ERROR, "Failed to convert json to binary: errcode=%d msg=%s",
status.error_code(), errmsg.c_str());
- gpr_log(GPR_ERROR, "JSON: ", json.c_str());
+ gpr_log(GPR_ERROR, "JSON: %s", json.c_str());
abort();
}
GPR_ASSERT(msg->ParseFromString(binary));
}
+grpc::string SerializeJson(const GRPC_CUSTOM_MESSAGE& msg,
+ const grpc::string& type) {
+ std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver(
+ google::protobuf::util::NewTypeResolverForDescriptorPool(
+ "type.googleapis.com",
+ google::protobuf::DescriptorPool::generated_pool()));
+ grpc::string binary;
+ grpc::string json_string;
+ msg.SerializeToString(&binary);
+ auto status =
+ BinaryToJsonString(type_resolver.get(), type, binary, &json_string);
+ GPR_ASSERT(status.ok());
+ return json_string;
+}
+
} // testing
} // grpc
diff --git a/test/cpp/qps/parse_json.h b/test/cpp/qps/parse_json.h
index 4b8ca79f21..ce1821f961 100644
--- a/test/cpp/qps/parse_json.h
+++ b/test/cpp/qps/parse_json.h
@@ -34,8 +34,8 @@
#ifndef TEST_QPS_PARSE_JSON_H
#define TEST_QPS_PARSE_JSON_H
+#include <grpc++/impl/codegen/config_protobuf.h>
#include <grpc++/support/config.h>
-#include <grpc++/support/config_protobuf.h>
namespace grpc {
namespace testing {
@@ -43,6 +43,9 @@ namespace testing {
void ParseJson(const grpc::string& json, const grpc::string& type,
GRPC_CUSTOM_MESSAGE* msg);
+grpc::string SerializeJson(const GRPC_CUSTOM_MESSAGE& msg,
+ const grpc::string& type);
+
} // testing
} // grpc
diff --git a/test/cpp/qps/perf_db_client.cc b/test/cpp/qps/perf_db_client.cc
deleted file mode 100644
index 98efd8c3e3..0000000000
--- a/test/cpp/qps/perf_db_client.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "test/cpp/qps/perf_db_client.h"
-
-namespace grpc {
-namespace testing {
-
-// sets the client and server config information
-void PerfDbClient::setConfigs(const ClientConfig& client_config,
- const ServerConfig& server_config) {
- client_config_ = client_config;
- server_config_ = server_config;
-}
-
-// sets the QPS
-void PerfDbClient::setQps(double qps) { qps_ = qps; }
-
-// sets the QPS per core
-void PerfDbClient::setQpsPerCore(double qps_per_core) {
- qps_per_core_ = qps_per_core;
-}
-
-// sets the 50th, 90th, 95th, 99th and 99.9th percentile latency
-void PerfDbClient::setLatencies(double perc_lat_50, double perc_lat_90,
- double perc_lat_95, double perc_lat_99,
- double perc_lat_99_point_9) {
- perc_lat_50_ = perc_lat_50;
- perc_lat_90_ = perc_lat_90;
- perc_lat_95_ = perc_lat_95;
- perc_lat_99_ = perc_lat_99;
- perc_lat_99_point_9_ = perc_lat_99_point_9;
-}
-
-// sets the server and client, user and system times
-void PerfDbClient::setTimes(double server_system_time, double server_user_time,
- double client_system_time,
- double client_user_time) {
- server_system_time_ = server_system_time;
- server_user_time_ = server_user_time;
- client_system_time_ = client_system_time;
- client_user_time_ = client_user_time;
-}
-
-// sends the data to the performance database server
-bool PerfDbClient::sendData(std::string hashed_id, std::string test_name,
- std::string sys_info, std::string tag) {
- // Data record request object
- SingleUserRecordRequest single_user_record_request;
-
- // setting access token, name of the test and the system information
- single_user_record_request.set_hashed_id(hashed_id);
- single_user_record_request.set_test_name(test_name);
- single_user_record_request.set_sys_info(sys_info);
- single_user_record_request.set_tag(tag);
-
- // setting configs
- *(single_user_record_request.mutable_client_config()) = client_config_;
- *(single_user_record_request.mutable_server_config()) = server_config_;
-
- Metrics* metrics = single_user_record_request.mutable_metrics();
-
- // setting metrcs in data record request
- if (qps_ != DBL_MIN) {
- metrics->set_qps(qps_);
- }
- if (qps_per_core_ != DBL_MIN) {
- metrics->set_qps_per_core(qps_per_core_);
- }
- if (perc_lat_50_ != DBL_MIN) {
- metrics->set_perc_lat_50(perc_lat_50_);
- }
- if (perc_lat_90_ != DBL_MIN) {
- metrics->set_perc_lat_90(perc_lat_90_);
- }
- if (perc_lat_95_ != DBL_MIN) {
- metrics->set_perc_lat_95(perc_lat_95_);
- }
- if (perc_lat_99_ != DBL_MIN) {
- metrics->set_perc_lat_99(perc_lat_99_);
- }
- if (perc_lat_99_point_9_ != DBL_MIN) {
- metrics->set_perc_lat_99_point_9(perc_lat_99_point_9_);
- }
- if (server_system_time_ != DBL_MIN) {
- metrics->set_server_system_time(server_system_time_);
- }
- if (server_user_time_ != DBL_MIN) {
- metrics->set_server_user_time(server_user_time_);
- }
- if (client_system_time_ != DBL_MIN) {
- metrics->set_client_system_time(client_system_time_);
- }
- if (client_user_time_ != DBL_MIN) {
- metrics->set_client_user_time(client_user_time_);
- }
-
- SingleUserRecordReply single_user_record_reply;
- ClientContext context;
-
- Status status = stub_->RecordSingleClientData(
- &context, single_user_record_request, &single_user_record_reply);
- if (status.ok()) {
- return true; // data sent to database successfully
- } else {
- return false; // error in data sending
- }
-}
-} // testing
-} // grpc
diff --git a/test/cpp/qps/perf_db_client.h b/test/cpp/qps/perf_db_client.h
deleted file mode 100644
index b74c70d86b..0000000000
--- a/test/cpp/qps/perf_db_client.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <cfloat>
-#include <iostream>
-#include <memory>
-#include <string>
-
-#include <grpc++/channel.h>
-#include <grpc++/client_context.h>
-#include <grpc++/create_channel.h>
-#include <grpc++/security/credentials.h>
-#include <grpc++/support/channel_arguments.h>
-#include <grpc/grpc.h>
-#include "src/proto/grpc/testing/perf_db.grpc.pb.h"
-
-namespace grpc {
-namespace testing {
-
-// Manages data sending to performance database server
-class PerfDbClient {
- public:
- PerfDbClient() {
- qps_ = DBL_MIN;
- qps_per_core_ = DBL_MIN;
- perc_lat_50_ = DBL_MIN;
- perc_lat_90_ = DBL_MIN;
- perc_lat_95_ = DBL_MIN;
- perc_lat_99_ = DBL_MIN;
- perc_lat_99_point_9_ = DBL_MIN;
- server_system_time_ = DBL_MIN;
- server_user_time_ = DBL_MIN;
- client_system_time_ = DBL_MIN;
- client_user_time_ = DBL_MIN;
- }
-
- void init(std::shared_ptr<Channel> channel) {
- stub_ = PerfDbTransfer::NewStub(channel);
- }
-
- ~PerfDbClient() {}
-
- // sets the client and server config information
- void setConfigs(const ClientConfig& client_config,
- const ServerConfig& server_config);
-
- // sets the qps
- void setQps(double qps);
-
- // sets the qps per core
- void setQpsPerCore(double qps_per_core);
-
- // sets the 50th, 90th, 95th, 99th and 99.9th percentile latency
- void setLatencies(double perc_lat_50, double perc_lat_90, double perc_lat_95,
- double perc_lat_99, double perc_lat_99_point_9);
-
- // sets the server and client, user and system times
- void setTimes(double server_system_time, double server_user_time,
- double client_system_time, double client_user_time);
-
- // sends the data to the performance database server
- bool sendData(std::string hashed_id, std::string test_name,
- std::string sys_info, std::string tag);
-
- private:
- std::unique_ptr<PerfDbTransfer::Stub> stub_;
- ClientConfig client_config_;
- ServerConfig server_config_;
- double qps_;
- double qps_per_core_;
- double perc_lat_50_;
- double perc_lat_90_;
- double perc_lat_95_;
- double perc_lat_99_;
- double perc_lat_99_point_9_;
- double server_system_time_;
- double server_user_time_;
- double client_system_time_;
- double client_user_time_;
-};
-
-} // namespace testing
-} // namespace grpc
diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc
index d7642f0e1e..f5d739f893 100644
--- a/test/cpp/qps/qps_json_driver.cc
+++ b/test/cpp/qps/qps_json_driver.cc
@@ -34,7 +34,7 @@
#include <memory>
#include <set>
-#include <grpc++/support/config_protobuf.h>
+#include <grpc++/impl/codegen/config_protobuf.h>
#include <gflags/gflags.h>
#include <grpc/support/log.h>
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index 3ae41399cf..2ec7d8676c 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -35,11 +35,9 @@
#include <fstream>
-#include <google/protobuf/util/json_util.h>
-#include <google/protobuf/util/type_resolver_util.h>
-
#include <grpc/support/log.h>
#include "test/cpp/qps/driver.h"
+#include "test/cpp/qps/parse_json.h"
#include "test/cpp/qps/stats.h"
namespace grpc {
@@ -104,18 +102,8 @@ void GprLogReporter::ReportTimes(const ScenarioResult& result) {
}
void JsonReporter::ReportQPS(const ScenarioResult& result) {
- std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver(
- google::protobuf::util::NewTypeResolverForDescriptorPool(
- "type.googleapis.com",
- google::protobuf::DescriptorPool::generated_pool()));
- grpc::string binary;
- grpc::string json_string;
- result.SerializeToString(&binary);
- auto status = BinaryToJsonString(
- type_resolver.get(), "type.googleapis.com/grpc.testing.ScenarioResult",
- binary, &json_string);
- GPR_ASSERT(status.ok());
-
+ grpc::string json_string =
+ SerializeJson(result, "type.googleapis.com/grpc.testing.ScenarioResult");
std::ofstream output_file(report_file_);
output_file << json_string;
output_file.close();
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index 8f04d84124..39cf498e7b 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -41,7 +41,6 @@
#include <grpc++/support/config.h>
#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/perf_db_client.h"
namespace grpc {
namespace testing {
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 1eddb1dc1d..c9954d0d02 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -37,7 +37,6 @@
#include <mutex>
#include <thread>
-#include <gflags/gflags.h>
#include <grpc++/generic/async_generic_service.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server.h>
@@ -48,7 +47,6 @@
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
-#include <gtest/gtest.h>
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/core/util/test_config.h"
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 9e64f470bf..c774985bfa 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -33,7 +33,6 @@
#include <thread>
-#include <gflags/gflags.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
diff --git a/test/cpp/util/byte_buffer_proto_helper.h b/test/cpp/util/byte_buffer_proto_helper.h
index 42cea59e33..007723c691 100644
--- a/test/cpp/util/byte_buffer_proto_helper.h
+++ b/test/cpp/util/byte_buffer_proto_helper.h
@@ -36,8 +36,8 @@
#include <memory>
+#include <grpc++/impl/codegen/config_protobuf.h>
#include <grpc++/support/byte_buffer.h>
-#include <grpc++/support/config_protobuf.h>
namespace grpc {
namespace testing {
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index 99fad7f2fe..98b9d930d6 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -86,7 +86,6 @@ Status CliCall::Call(std::shared_ptr<grpc::Channel> channel,
cq.Next(&got_tag, &ok);
if (!ok) {
std::cout << "Failed to read response." << std::endl;
- return Status(StatusCode::INTERNAL, "Failed to read response");
}
grpc::Status status;
call->Finish(&status, tag(5));
@@ -103,6 +102,7 @@ Status CliCall::Call(std::shared_ptr<grpc::Channel> channel,
slices[i].size());
}
}
+
*server_initial_metadata = ctx.GetServerInitialMetadata();
*server_trailing_metadata = ctx.GetServerTrailingMetadata();
return status;
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index 68cf4114a8..c52e48bae6 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -32,32 +32,33 @@
*/
/*
- A command line tool to talk to any grpc server.
+ A command line tool to talk to a grpc server.
Example of talking to grpc interop server:
- 1. Prepare request binary file:
- a. create a text file input.txt, containing the following:
- response_size: 10
- payload: {
- body: "hello world"
- }
- b. under grpc/ run
- protoc --proto_path=src/proto/grpc/testing/ \
- --encode=grpc.testing.SimpleRequest
- src/proto/grpc/testing/messages.proto \
- < input.txt > input.bin
- 2. Start a server
- make interop_server && bins/opt/interop_server --port=50051
- 3. Run the tool
- make grpc_cli && bins/opt/grpc_cli call localhost:50051 \
- /grpc.testing.TestService/UnaryCall --enable_ssl=false \
- --input_binary_file=input.bin --output_binary_file=output.bin
- 4. Decode response
- protoc --proto_path=src/proto/grpc/testing/ \
- --decode=grpc.testing.SimpleResponse src/proto/grpc/testing/messages.proto \
- < output.bin > output.txt
- 5. Now the text form of response should be in output.txt
- Optionally, metadata can be passed to server via flag --metadata, e.g.
- --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
+ grpc_cli call localhost:50051 UnaryCall src/proto/grpc/testing/test.proto \
+ "response_size:10" --enable_ssl=false
+
+ Options:
+ 1. --proto_path, if your proto file is not under current working directory,
+ use this flag to provide a search root. It should work similar to the
+ counterpart in protoc.
+ 2. --metadata specifies metadata to be sent to the server, such as:
+ --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
+ 3. --enable_ssl, whether to use tls.
+ 4. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
+ 3. --input_binary_file, a file containing the serialized request. The file
+ can be generated by calling something like:
+ protoc --proto_path=src/proto/grpc/testing/ \
+ --encode=grpc.testing.SimpleRequest \
+ src/proto/grpc/testing/messages.proto \
+ < input.txt > input.bin
+ If this is used and no proto file is provided in the argument list, the
+ method string has to be exact in the form of /package.service/method.
+ 4. --output_binary_file, a file to write binary format response into, it can
+ be later decoded using protoc:
+ protoc --proto_path=src/proto/grpc/testing/ \
+ --decode=grpc.testing.SimpleResponse \
+ src/proto/grpc/testing/messages.proto \
+ < output.bin > output.txt
*/
#include <fstream>
@@ -72,6 +73,7 @@
#include <grpc/grpc.h>
#include "test/cpp/util/cli_call.h"
+#include "test/cpp/util/proto_file_parser.h"
#include "test/cpp/util/string_ref_helper.h"
#include "test/cpp/util/test_config.h"
@@ -79,10 +81,11 @@ DEFINE_bool(enable_ssl, true, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
DEFINE_string(input_binary_file, "",
"Path to input file containing serialized request.");
-DEFINE_string(output_binary_file, "output.bin",
+DEFINE_string(output_binary_file, "",
"Path to output file to write serialized response.");
DEFINE_string(metadata, "",
"Metadata to send to server, in the form of key1:val1:key2:val2");
+DEFINE_string(proto_path, ".", "Path to look for the proto file.");
void ParseMetadataFlag(
std::multimap<grpc::string, grpc::string>* client_metadata) {
@@ -126,28 +129,51 @@ void PrintMetadata(const T& m, const grpc::string& message) {
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
- if (argc < 4 || grpc::string(argv[1]) != "call") {
- std::cout << "Usage: grpc_cli call server_host:port full_method_string\n"
- << "Example: grpc_cli call service.googleapis.com "
- << "/grpc.testing.TestService/UnaryCall "
- << "--input_binary_file=input.bin --output_binary_file=output.bin"
- << std::endl;
+ if (argc < 4 || argc == 5 || grpc::string(argv[1]) != "call") {
+ std::cout << "Usage: grpc_cli call server_host:port method_name "
+ << "[proto file] [text format request] [<options>]" << std::endl;
}
+
+ grpc::string file_name;
+ grpc::string request_text;
grpc::string server_address(argv[2]);
- // TODO(yangg) basic check of method string
- grpc::string method(argv[3]);
+ grpc::string method_name(argv[3]);
+ std::unique_ptr<grpc::testing::ProtoFileParser> parser;
+ grpc::string serialized_request_proto;
- if (FLAGS_input_binary_file.empty()) {
- std::cout << "Missing --input_binary_file for serialized request."
- << std::endl;
+ if (argc == 6) {
+ file_name = argv[4];
+ // TODO(yangg) read from stdin as well?
+ request_text = argv[5];
+ }
+
+ if (request_text.empty() && FLAGS_input_binary_file.empty()) {
+ std::cout << "Missing input. Use text format input or "
+ << "--input_binary_file for serialized request" << std::endl;
return 1;
+ } else if (!request_text.empty()) {
+ parser.reset(new grpc::testing::ProtoFileParser(FLAGS_proto_path, file_name,
+ method_name));
+ method_name = parser->GetFullMethodName();
+ if (parser->HasError()) {
+ return 1;
+ }
}
- std::cout << "connecting to " << server_address << std::endl;
- std::ifstream input_file(FLAGS_input_binary_file,
- std::ios::in | std::ios::binary);
- std::stringstream input_stream;
- input_stream << input_file.rdbuf();
+ if (parser) {
+ serialized_request_proto =
+ parser->GetSerializedProto(request_text, true /* is_request */);
+ if (parser->HasError()) {
+ return 1;
+ }
+ } else if (!FLAGS_input_binary_file.empty()) {
+ std::ifstream input_file(FLAGS_input_binary_file,
+ std::ios::in | std::ios::binary);
+ std::stringstream input_stream;
+ input_stream << input_file.rdbuf();
+ serialized_request_proto = input_stream.str();
+ }
+ std::cout << "connecting to " << server_address << std::endl;
std::shared_ptr<grpc::ChannelCredentials> creds;
if (!FLAGS_enable_ssl) {
@@ -162,25 +188,34 @@ int main(int argc, char** argv) {
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, creds);
- grpc::string response;
+ grpc::string serialized_response_proto;
std::multimap<grpc::string, grpc::string> client_metadata;
std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
server_trailing_metadata;
ParseMetadataFlag(&client_metadata);
PrintMetadata(client_metadata, "Sending client initial metadata:");
grpc::Status s = grpc::testing::CliCall::Call(
- channel, method, input_stream.str(), &response, client_metadata,
- &server_initial_metadata, &server_trailing_metadata);
+ channel, 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,
"Received trailing metadata from server:");
if (s.ok()) {
std::cout << "Rpc succeeded with OK status" << std::endl;
- if (!response.empty()) {
+ if (parser) {
+ grpc::string response_text = parser->GetTextFormat(
+ serialized_response_proto, false /* is_request */);
+ if (parser->HasError()) {
+ return 1;
+ }
+ std::cout << "Response: \n " << response_text << std::endl;
+ }
+ if (!FLAGS_output_binary_file.empty()) {
std::ofstream output_file(FLAGS_output_binary_file,
std::ios::trunc | std::ios::binary);
- output_file << response;
+ output_file << serialized_response_proto;
}
} else {
std::cout << "Rpc failed with status code " << s.error_code()
diff --git a/test/cpp/util/metrics_server.cc b/test/cpp/util/metrics_server.cc
index cc6b39b753..1c7cd6382a 100644
--- a/test/cpp/util/metrics_server.cc
+++ b/test/cpp/util/metrics_server.cc
@@ -99,7 +99,7 @@ std::shared_ptr<QpsGauge> MetricsServiceImpl::CreateQpsGauge(
std::lock_guard<std::mutex> lock(mu_);
std::shared_ptr<QpsGauge> qps_gauge(new QpsGauge());
- const auto p = qps_gauges_.emplace(name, qps_gauge);
+ const auto p = qps_gauges_.insert(std::make_pair(name, qps_gauge));
// p.first is an iterator pointing to <name, shared_ptr<QpsGauge>> pair.
// p.second is a boolean which is set to 'true' if the QpsGauge is
@@ -114,7 +114,7 @@ std::shared_ptr<QpsGauge> MetricsServiceImpl::CreateQpsGauge(
std::unique_ptr<grpc::Server> MetricsServiceImpl::StartServer(int port) {
gpr_log(GPR_INFO, "Building metrics server..");
- const grpc::string address = "0.0.0.0:" + std::to_string(port);
+ const grpc::string address = "0.0.0.0:" + grpc::to_string(port);
ServerBuilder builder;
builder.AddListeningPort(address, grpc::InsecureServerCredentials());
diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc
new file mode 100644
index 0000000000..25aec329eb
--- /dev/null
+++ b/test/cpp/util/proto_file_parser.cc
@@ -0,0 +1,178 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/cpp/util/proto_file_parser.h"
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <google/protobuf/text_format.h>
+#include <grpc++/support/config.h>
+
+namespace grpc {
+namespace testing {
+namespace {
+
+// Match the user input method string to the full_name from method descriptor.
+bool MethodNameMatch(const grpc::string& full_name, const grpc::string& input) {
+ grpc::string clean_input = input;
+ std::replace(clean_input.begin(), clean_input.end(), '/', '.');
+ if (clean_input.size() > full_name.size()) {
+ return false;
+ }
+ return full_name.compare(full_name.size() - clean_input.size(),
+ clean_input.size(), clean_input) == 0;
+}
+} // namespace
+
+class ErrorPrinter
+ : public google::protobuf::compiler::MultiFileErrorCollector {
+ public:
+ explicit ErrorPrinter(ProtoFileParser* parser) : parser_(parser) {}
+
+ void AddError(const grpc::string& filename, int line, int column,
+ const grpc::string& message) GRPC_OVERRIDE {
+ std::ostringstream oss;
+ oss << "error " << filename << " " << line << " " << column << " "
+ << message << "\n";
+ parser_->LogError(oss.str());
+ }
+
+ void AddWarning(const grpc::string& filename, int line, int column,
+ const grpc::string& message) GRPC_OVERRIDE {
+ std::cout << "warning " << filename << " " << line << " " << column << " "
+ << message << std::endl;
+ }
+
+ private:
+ ProtoFileParser* parser_; // not owned
+};
+
+ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
+ const grpc::string& file_name,
+ const grpc::string& method)
+ : has_error_(false) {
+ source_tree_.MapPath("", proto_path);
+ error_printer_.reset(new ErrorPrinter(this));
+ importer_.reset(new google::protobuf::compiler::Importer(
+ &source_tree_, error_printer_.get()));
+ const auto* file_desc = importer_->Import(file_name);
+ if (!file_desc) {
+ LogError("");
+ return;
+ }
+ dynamic_factory_.reset(
+ new google::protobuf::DynamicMessageFactory(importer_->pool()));
+
+ const google::protobuf::MethodDescriptor* method_descriptor = nullptr;
+ for (int i = 0; !method_descriptor && i < file_desc->service_count(); i++) {
+ const auto* service_desc = file_desc->service(i);
+ for (int j = 0; j < service_desc->method_count(); j++) {
+ const auto* method_desc = service_desc->method(j);
+ if (MethodNameMatch(method_desc->full_name(), method)) {
+ if (method_descriptor) {
+ std::ostringstream error_stream("Ambiguous method names: ");
+ error_stream << method_descriptor->full_name() << " ";
+ error_stream << method_desc->full_name();
+ LogError(error_stream.str());
+ }
+ method_descriptor = method_desc;
+ }
+ }
+ }
+ if (!method_descriptor) {
+ LogError("Method name not found");
+ }
+ if (has_error_) {
+ return;
+ }
+ full_method_name_ = method_descriptor->full_name();
+ size_t last_dot = full_method_name_.find_last_of('.');
+ if (last_dot != grpc::string::npos) {
+ full_method_name_[last_dot] = '/';
+ }
+ full_method_name_.insert(full_method_name_.begin(), '/');
+
+ request_prototype_.reset(
+ dynamic_factory_->GetPrototype(method_descriptor->input_type())->New());
+ response_prototype_.reset(
+ dynamic_factory_->GetPrototype(method_descriptor->output_type())->New());
+}
+
+ProtoFileParser::~ProtoFileParser() {}
+
+grpc::string ProtoFileParser::GetSerializedProto(
+ const grpc::string& text_format_proto, bool is_request) {
+ grpc::string serialized;
+ grpc::protobuf::Message* msg =
+ is_request ? request_prototype_.get() : response_prototype_.get();
+ bool ok =
+ google::protobuf::TextFormat::ParseFromString(text_format_proto, msg);
+ if (!ok) {
+ LogError("Failed to parse text format to proto.");
+ return "";
+ }
+ ok = request_prototype_->SerializeToString(&serialized);
+ if (!ok) {
+ LogError("Failed to serialize proto.");
+ return "";
+ }
+ return serialized;
+}
+
+grpc::string ProtoFileParser::GetTextFormat(
+ const grpc::string& serialized_proto, bool is_request) {
+ grpc::protobuf::Message* msg =
+ is_request ? request_prototype_.get() : response_prototype_.get();
+ if (!msg->ParseFromString(serialized_proto)) {
+ LogError("Failed to deserialize proto.");
+ return "";
+ }
+ grpc::string text_format;
+ if (!google::protobuf::TextFormat::PrintToString(*msg, &text_format)) {
+ LogError("Failed to print proto message to text format");
+ return "";
+ }
+ return text_format;
+}
+
+void ProtoFileParser::LogError(const grpc::string& error_msg) {
+ if (!error_msg.empty()) {
+ std::cout << error_msg << std::endl;
+ }
+ has_error_ = true;
+}
+
+} // namespace testing
+} // namespace grpc
diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h
new file mode 100644
index 0000000000..46cdd66503
--- /dev/null
+++ b/test/cpp/util/proto_file_parser.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_TEST_CPP_UTIL_PROTO_FILE_PARSER_H
+#define GRPC_TEST_CPP_UTIL_PROTO_FILE_PARSER_H
+
+#include <memory>
+
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/dynamic_message.h>
+
+#include "src/compiler/config.h"
+
+namespace grpc {
+namespace testing {
+class ErrorPrinter;
+
+// Find method and associated request/response types.
+class ProtoFileParser {
+ public:
+ // The given proto file_name will be searched in a source tree rooted from
+ // proto_path. The method could be a partial string such as Service.Method or
+ // even just Method. It will log an error if there is ambiguity.
+ ProtoFileParser(const grpc::string& proto_path, const grpc::string& file_name,
+ const grpc::string& method);
+ ~ProtoFileParser();
+
+ grpc::string GetFullMethodName() const { return full_method_name_; }
+
+ grpc::string GetSerializedProto(const grpc::string& text_format_proto,
+ bool is_request);
+
+ grpc::string GetTextFormat(const grpc::string& serialized_proto,
+ bool is_request);
+
+ bool HasError() const { return has_error_; }
+
+ void LogError(const grpc::string& error_msg);
+
+ private:
+ bool has_error_;
+ grpc::string request_text_;
+ grpc::string full_method_name_;
+ google::protobuf::compiler::DiskSourceTree source_tree_;
+ std::unique_ptr<ErrorPrinter> error_printer_;
+ std::unique_ptr<google::protobuf::compiler::Importer> importer_;
+ std::unique_ptr<google::protobuf::DynamicMessageFactory> dynamic_factory_;
+ std::unique_ptr<grpc::protobuf::Message> request_prototype_;
+ std::unique_ptr<grpc::protobuf::Message> response_prototype_;
+};
+
+} // namespace testing
+} // namespace grpc
+
+#endif // GRPC_TEST_CPP_UTIL_PROTO_FILE_PARSER_H
diff --git a/test/cpp/util/proto_reflection_descriptor_database.cc b/test/cpp/util/proto_reflection_descriptor_database.cc
new file mode 100644
index 0000000000..25b720aee0
--- /dev/null
+++ b/test/cpp/util/proto_reflection_descriptor_database.cc
@@ -0,0 +1,316 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/cpp/util/proto_reflection_descriptor_database.h"
+
+#include <vector>
+
+#include <grpc/support/log.h>
+
+using grpc::reflection::v1alpha::ServerReflection;
+using grpc::reflection::v1alpha::ServerReflectionRequest;
+using grpc::reflection::v1alpha::ServerReflectionResponse;
+using grpc::reflection::v1alpha::ListServiceResponse;
+using grpc::reflection::v1alpha::ErrorResponse;
+
+namespace grpc {
+
+ProtoReflectionDescriptorDatabase::ProtoReflectionDescriptorDatabase(
+ std::unique_ptr<ServerReflection::Stub> stub)
+ : stub_(std::move(stub)) {}
+
+ProtoReflectionDescriptorDatabase::ProtoReflectionDescriptorDatabase(
+ std::shared_ptr<grpc::Channel> channel)
+ : stub_(ServerReflection::NewStub(channel)) {}
+
+ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {}
+
+bool ProtoReflectionDescriptorDatabase::FindFileByName(
+ const string& filename, google::protobuf::FileDescriptorProto* output) {
+ if (cached_db_.FindFileByName(filename, output)) {
+ return true;
+ }
+
+ if (known_files_.find(filename) != known_files_.end()) {
+ return false;
+ }
+
+ ServerReflectionRequest request;
+ request.set_file_by_filename(filename);
+ ServerReflectionResponse response;
+
+ DoOneRequest(request, response);
+
+ if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse) {
+ AddFileFromResponse(response.file_descriptor_response());
+ } else if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
+ const ErrorResponse error = response.error_response();
+ if (error.error_code() == StatusCode::NOT_FOUND) {
+ gpr_log(GPR_INFO, "NOT_FOUND from server for FindFileByName(%s)",
+ filename.c_str());
+ } else {
+ gpr_log(GPR_INFO,
+ "Error on FindFileByName(%s)\n\tError code: %d\n"
+ "\tError Message: %s",
+ filename.c_str(), error.error_code(),
+ error.error_message().c_str());
+ }
+ } else {
+ gpr_log(
+ GPR_INFO,
+ "Error on FindFileByName(%s) response type\n"
+ "\tExpecting: %d\n\tReceived: %d",
+ filename.c_str(),
+ ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse,
+ response.message_response_case());
+ }
+
+ return cached_db_.FindFileByName(filename, output);
+}
+
+bool ProtoReflectionDescriptorDatabase::FindFileContainingSymbol(
+ const string& symbol_name, google::protobuf::FileDescriptorProto* output) {
+ if (cached_db_.FindFileContainingSymbol(symbol_name, output)) {
+ return true;
+ }
+
+ if (missing_symbols_.find(symbol_name) != missing_symbols_.end()) {
+ return false;
+ }
+
+ ServerReflectionRequest request;
+ request.set_file_containing_symbol(symbol_name);
+ ServerReflectionResponse response;
+
+ DoOneRequest(request, response);
+
+ if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse) {
+ AddFileFromResponse(response.file_descriptor_response());
+ } else if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
+ const ErrorResponse error = response.error_response();
+ if (error.error_code() == StatusCode::NOT_FOUND) {
+ missing_symbols_.insert(symbol_name);
+ gpr_log(GPR_INFO,
+ "NOT_FOUND from server for FindFileContainingSymbol(%s)",
+ symbol_name.c_str());
+ } else {
+ gpr_log(GPR_INFO,
+ "Error on FindFileContainingSymbol(%s)\n"
+ "\tError code: %d\n\tError Message: %s",
+ symbol_name.c_str(), error.error_code(),
+ error.error_message().c_str());
+ }
+ } else {
+ gpr_log(
+ GPR_INFO,
+ "Error on FindFileContainingSymbol(%s) response type\n"
+ "\tExpecting: %d\n\tReceived: %d",
+ symbol_name.c_str(),
+ ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse,
+ response.message_response_case());
+ }
+ return cached_db_.FindFileContainingSymbol(symbol_name, output);
+}
+
+bool ProtoReflectionDescriptorDatabase::FindFileContainingExtension(
+ const string& containing_type, int field_number,
+ google::protobuf::FileDescriptorProto* output) {
+ if (cached_db_.FindFileContainingExtension(containing_type, field_number,
+ output)) {
+ return true;
+ }
+
+ if (missing_extensions_.find(containing_type) != missing_extensions_.end() &&
+ missing_extensions_[containing_type].find(field_number) !=
+ missing_extensions_[containing_type].end()) {
+ gpr_log(GPR_INFO, "nested map.");
+ return false;
+ }
+
+ ServerReflectionRequest request;
+ request.mutable_file_containing_extension()->set_containing_type(
+ containing_type);
+ request.mutable_file_containing_extension()->set_extension_number(
+ field_number);
+ ServerReflectionResponse response;
+
+ DoOneRequest(request, response);
+
+ if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse) {
+ AddFileFromResponse(response.file_descriptor_response());
+ } else if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
+ const ErrorResponse error = response.error_response();
+ if (error.error_code() == StatusCode::NOT_FOUND) {
+ if (missing_extensions_.find(containing_type) ==
+ missing_extensions_.end()) {
+ missing_extensions_[containing_type] = {};
+ }
+ missing_extensions_[containing_type].insert(field_number);
+ gpr_log(GPR_INFO,
+ "NOT_FOUND from server for FindFileContainingExtension(%s, %d)",
+ containing_type.c_str(), field_number);
+ } else {
+ gpr_log(GPR_INFO,
+ "Error on FindFileContainingExtension(%s, %d)\n"
+ "\tError code: %d\n\tError Message: %s",
+ containing_type.c_str(), field_number, error.error_code(),
+ error.error_message().c_str());
+ }
+ } else {
+ gpr_log(
+ GPR_INFO,
+ "Error on FindFileContainingExtension(%s, %d) response type\n"
+ "\tExpecting: %d\n\tReceived: %d",
+ containing_type.c_str(), field_number,
+ ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse,
+ response.message_response_case());
+ }
+
+ return cached_db_.FindFileContainingExtension(containing_type, field_number,
+ output);
+}
+
+bool ProtoReflectionDescriptorDatabase::FindAllExtensionNumbers(
+ const string& extendee_type, std::vector<int>* output) {
+ if (cached_extension_numbers_.find(extendee_type) !=
+ cached_extension_numbers_.end()) {
+ *output = cached_extension_numbers_[extendee_type];
+ return true;
+ }
+
+ ServerReflectionRequest request;
+ request.set_all_extension_numbers_of_type(extendee_type);
+ ServerReflectionResponse response;
+
+ DoOneRequest(request, response);
+
+ if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::
+ kAllExtensionNumbersResponse) {
+ auto number = response.all_extension_numbers_response().extension_number();
+ *output = std::vector<int>(number.begin(), number.end());
+ cached_extension_numbers_[extendee_type] = *output;
+ return true;
+ } else if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
+ const ErrorResponse error = response.error_response();
+ if (error.error_code() == StatusCode::NOT_FOUND) {
+ gpr_log(GPR_INFO, "NOT_FOUND from server for FindAllExtensionNumbers(%s)",
+ extendee_type.c_str());
+ } else {
+ gpr_log(GPR_INFO,
+ "Error on FindAllExtensionNumbersExtension(%s)\n"
+ "\tError code: %d\n\tError Message: %s",
+ extendee_type.c_str(), error.error_code(),
+ error.error_message().c_str());
+ }
+ }
+ return false;
+}
+
+bool ProtoReflectionDescriptorDatabase::GetServices(
+ std::vector<std::string>* output) {
+ ServerReflectionRequest request;
+ request.set_list_services("");
+ ServerReflectionResponse response;
+
+ DoOneRequest(request, response);
+
+ if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kListServicesResponse) {
+ const ListServiceResponse ls_response = response.list_services_response();
+ for (int i = 0; i < ls_response.service_size(); ++i) {
+ (*output).push_back(ls_response.service(i).name());
+ }
+ return true;
+ } else if (response.message_response_case() ==
+ ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
+ const ErrorResponse error = response.error_response();
+ gpr_log(GPR_INFO,
+ "Error on GetServices()\n\tError code: %d\n"
+ "\tError Message: %s",
+ error.error_code(), error.error_message().c_str());
+ } else {
+ gpr_log(
+ GPR_INFO,
+ "Error on GetServices() response type\n\tExpecting: %d\n\tReceived: %d",
+ ServerReflectionResponse::MessageResponseCase::kListServicesResponse,
+ response.message_response_case());
+ }
+ return false;
+}
+
+const google::protobuf::FileDescriptorProto
+ProtoReflectionDescriptorDatabase::ParseFileDescriptorProtoResponse(
+ const std::string& byte_fd_proto) {
+ google::protobuf::FileDescriptorProto file_desc_proto;
+ file_desc_proto.ParseFromString(byte_fd_proto);
+ return file_desc_proto;
+}
+
+void ProtoReflectionDescriptorDatabase::AddFileFromResponse(
+ const grpc::reflection::v1alpha::FileDescriptorResponse& response) {
+ for (int i = 0; i < response.file_descriptor_proto_size(); ++i) {
+ const google::protobuf::FileDescriptorProto file_proto =
+ ParseFileDescriptorProtoResponse(response.file_descriptor_proto(i));
+ if (known_files_.find(file_proto.name()) == known_files_.end()) {
+ known_files_.insert(file_proto.name());
+ cached_db_.Add(file_proto);
+ }
+ }
+}
+
+const std::shared_ptr<ProtoReflectionDescriptorDatabase::ClientStream>
+ProtoReflectionDescriptorDatabase::GetStream() {
+ if (!stream_) {
+ stream_ = stub_->ServerReflectionInfo(&ctx_);
+ }
+ return stream_;
+}
+
+void ProtoReflectionDescriptorDatabase::DoOneRequest(
+ const ServerReflectionRequest& request,
+ ServerReflectionResponse& response) {
+ stream_mutex_.lock();
+ GetStream()->Write(request);
+ GetStream()->Read(&response);
+ stream_mutex_.unlock();
+}
+
+} // namespace grpc
diff --git a/test/cpp/util/proto_reflection_descriptor_database.h b/test/cpp/util/proto_reflection_descriptor_database.h
new file mode 100644
index 0000000000..99c00675bb
--- /dev/null
+++ b/test/cpp/util/proto_reflection_descriptor_database.h
@@ -0,0 +1,131 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef GRPC_TEST_CPP_PROTO_SERVER_REFLECTION_DATABSE_H
+#define GRPC_TEST_CPP_PROTO_SERVER_REFLECTION_DATABSE_H
+
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor_database.h>
+#include <grpc++/ext/reflection.grpc.pb.h>
+#include <grpc++/grpc++.h>
+
+namespace grpc {
+
+// ProtoReflectionDescriptorDatabase takes a stub of ServerReflection and
+// provides the methods defined by DescriptorDatabase interfaces. It can be used
+// to feed a DescriptorPool instance.
+class ProtoReflectionDescriptorDatabase
+ : public google::protobuf::DescriptorDatabase {
+ public:
+ explicit ProtoReflectionDescriptorDatabase(
+ std::unique_ptr<reflection::v1alpha::ServerReflection::Stub> stub);
+
+ explicit ProtoReflectionDescriptorDatabase(
+ std::shared_ptr<grpc::Channel> channel);
+
+ virtual ~ProtoReflectionDescriptorDatabase();
+
+ // The following four methods implement DescriptorDatabase interfaces.
+ //
+ // Find a file by file name. Fills in in *output and returns true if found.
+ // Otherwise, returns false, leaving the contents of *output undefined.
+ bool FindFileByName(const string& filename,
+ google::protobuf::FileDescriptorProto* output)
+ GRPC_OVERRIDE;
+
+ // Find the file that declares the given fully-qualified symbol name.
+ // If found, fills in *output and returns true, otherwise returns false
+ // and leaves *output undefined.
+ bool FindFileContainingSymbol(const string& symbol_name,
+ google::protobuf::FileDescriptorProto* output)
+ GRPC_OVERRIDE;
+
+ // Find the file which defines an extension extending the given message type
+ // with the given field number. If found, fills in *output and returns true,
+ // otherwise returns false and leaves *output undefined. containing_type
+ // must be a fully-qualified type name.
+ bool FindFileContainingExtension(
+ const string& containing_type, int field_number,
+ google::protobuf::FileDescriptorProto* output) GRPC_OVERRIDE;
+
+ // Finds the tag numbers used by all known extensions of
+ // extendee_type, and appends them to output in an undefined
+ // order. This method is best-effort: it's not guaranteed that the
+ // database will find all extensions, and it's not guaranteed that
+ // FindFileContainingExtension will return true on all of the found
+ // numbers. Returns true if the search was successful, otherwise
+ // returns false and leaves output unchanged.
+ bool FindAllExtensionNumbers(const string& extendee_type,
+ std::vector<int>* output) GRPC_OVERRIDE;
+
+ // Provide a list of full names of registered services
+ bool GetServices(std::vector<std::string>* output);
+
+ private:
+ typedef ClientReaderWriter<
+ grpc::reflection::v1alpha::ServerReflectionRequest,
+ grpc::reflection::v1alpha::ServerReflectionResponse>
+ ClientStream;
+
+ const google::protobuf::FileDescriptorProto ParseFileDescriptorProtoResponse(
+ const std::string& byte_fd_proto);
+
+ void AddFileFromResponse(
+ const grpc::reflection::v1alpha::FileDescriptorResponse& response);
+
+ const std::shared_ptr<ClientStream> GetStream();
+
+ void DoOneRequest(
+ const grpc::reflection::v1alpha::ServerReflectionRequest& request,
+ grpc::reflection::v1alpha::ServerReflectionResponse& response);
+
+ std::shared_ptr<ClientStream> stream_;
+ grpc::ClientContext ctx_;
+ std::unique_ptr<grpc::reflection::v1alpha::ServerReflection::Stub> stub_;
+ std::unordered_set<string> known_files_;
+ std::unordered_set<string> missing_symbols_;
+ std::unordered_map<string, std::unordered_set<int>> missing_extensions_;
+ std::unordered_map<string, std::vector<int>> cached_extension_numbers_;
+ std::mutex stream_mutex_;
+
+ google::protobuf::SimpleDescriptorDatabase cached_db_;
+};
+
+} // namespace grpc
+
+#endif // GRPC_TEST_CPP_METRICS_SERVER_H
diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc
index 9c09a73115..6e68f59e6a 100644
--- a/test/cpp/util/test_credentials_provider.cc
+++ b/test/cpp/util/test_credentials_provider.cc
@@ -41,15 +41,9 @@
#include "test/core/end2end/data/ssl_test_data.h"
+namespace grpc {
namespace {
-using grpc::ChannelArguments;
-using grpc::ChannelCredentials;
-using grpc::InsecureChannelCredentials;
-using grpc::InsecureServerCredentials;
-using grpc::ServerCredentials;
-using grpc::SslCredentialsOptions;
-using grpc::SslServerCredentialsOptions;
using grpc::testing::CredentialTypeProvider;
// Provide test credentials. Thread-safe.
@@ -69,19 +63,27 @@ class CredentialsProvider {
class DefaultCredentialsProvider : public CredentialsProvider {
public:
- ~DefaultCredentialsProvider() override {}
+ ~DefaultCredentialsProvider() GRPC_OVERRIDE {}
- void AddSecureType(
- const grpc::string& type,
- std::unique_ptr<CredentialTypeProvider> type_provider) override {
+ void AddSecureType(const grpc::string& type,
+ std::unique_ptr<CredentialTypeProvider> type_provider)
+ GRPC_OVERRIDE {
// This clobbers any existing entry for type, except the defaults, which
// can't be clobbered.
grpc::unique_lock<grpc::mutex> lock(mu_);
- added_secure_types_[type] = std::move(type_provider);
+ auto it = std::find(added_secure_type_names_.begin(),
+ added_secure_type_names_.end(), type);
+ if (it == added_secure_type_names_.end()) {
+ added_secure_type_names_.push_back(type);
+ added_secure_type_providers_.push_back(std::move(type_provider));
+ } else {
+ added_secure_type_providers_[it - added_secure_type_names_.begin()] =
+ std::move(type_provider);
+ }
}
std::shared_ptr<ChannelCredentials> GetChannelCredentials(
- const grpc::string& type, ChannelArguments* args) override {
+ const grpc::string& type, ChannelArguments* args) GRPC_OVERRIDE {
if (type == grpc::testing::kInsecureCredentialsType) {
return InsecureChannelCredentials();
} else if (type == grpc::testing::kTlsCredentialsType) {
@@ -90,17 +92,19 @@ class DefaultCredentialsProvider : public CredentialsProvider {
return SslCredentials(ssl_opts);
} else {
grpc::unique_lock<grpc::mutex> lock(mu_);
- auto it(added_secure_types_.find(type));
- if (it == added_secure_types_.end()) {
+ auto it(std::find(added_secure_type_names_.begin(),
+ added_secure_type_names_.end(), type));
+ if (it == added_secure_type_names_.end()) {
gpr_log(GPR_ERROR, "Unsupported credentials type %s.", type.c_str());
return nullptr;
}
- return it->second->GetChannelCredentials(args);
+ return added_secure_type_providers_[it - added_secure_type_names_.begin()]
+ ->GetChannelCredentials(args);
}
}
std::shared_ptr<ServerCredentials> GetServerCredentials(
- const grpc::string& type) override {
+ const grpc::string& type) GRPC_OVERRIDE {
if (type == grpc::testing::kInsecureCredentialsType) {
return InsecureServerCredentials();
} else if (type == grpc::testing::kTlsCredentialsType) {
@@ -112,28 +116,32 @@ class DefaultCredentialsProvider : public CredentialsProvider {
return SslServerCredentials(ssl_opts);
} else {
grpc::unique_lock<grpc::mutex> lock(mu_);
- auto it(added_secure_types_.find(type));
- if (it == added_secure_types_.end()) {
+ auto it(std::find(added_secure_type_names_.begin(),
+ added_secure_type_names_.end(), type));
+ if (it == added_secure_type_names_.end()) {
gpr_log(GPR_ERROR, "Unsupported credentials type %s.", type.c_str());
return nullptr;
}
- return it->second->GetServerCredentials();
+ return added_secure_type_providers_[it - added_secure_type_names_.begin()]
+ ->GetServerCredentials();
}
}
- std::vector<grpc::string> GetSecureCredentialsTypeList() override {
+ std::vector<grpc::string> GetSecureCredentialsTypeList() GRPC_OVERRIDE {
std::vector<grpc::string> types;
types.push_back(grpc::testing::kTlsCredentialsType);
grpc::unique_lock<grpc::mutex> lock(mu_);
- for (const auto& type_pair : added_secure_types_) {
- types.push_back(type_pair.first);
+ for (auto it = added_secure_type_names_.begin();
+ it != added_secure_type_names_.end(); it++) {
+ types.push_back(*it);
}
return types;
}
private:
grpc::mutex mu_;
- std::unordered_map<grpc::string, std::unique_ptr<CredentialTypeProvider> >
- added_secure_types_;
+ std::vector<grpc::string> added_secure_type_names_;
+ std::vector<std::unique_ptr<CredentialTypeProvider>>
+ added_secure_type_providers_;
};
gpr_once g_once_init_provider = GPR_ONCE_INIT;
@@ -148,7 +156,6 @@ CredentialsProvider* GetProvider() {
} // namespace
-namespace grpc {
namespace testing {
void AddSecureType(const grpc::string& type,