diff options
Diffstat (limited to 'test/cpp')
32 files changed, 412 insertions, 729 deletions
diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc index 0e43d4e1e0..66225ff335 100644 --- a/test/cpp/common/auth_property_iterator_test.cc +++ b/test/cpp/common/auth_property_iterator_test.cc @@ -38,7 +38,7 @@ #include "test/cpp/util/string_ref_helper.h" extern "C" { -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" } using ::grpc::testing::ToString; diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc index 067361334d..b131452f73 100644 --- a/test/cpp/common/secure_auth_context_test.cc +++ b/test/cpp/common/secure_auth_context_test.cc @@ -38,7 +38,7 @@ #include "test/cpp/util/string_ref_helper.h" extern "C" { -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" } using grpc::testing::ToString; diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 45f5eb1ddd..b839801500 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -819,7 +819,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 +881,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()); @@ -1026,9 +1026,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()); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index e3408bff75..f52aa52f39 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -48,7 +48,7 @@ #include <grpc/support/time.h> #include <gtest/gtest.h> -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/port.h" 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 02043a89d3..2c05db345b 100644 --- a/test/cpp/end2end/hybrid_end2end_test.cc +++ b/test/cpp/end2end/hybrid_end2end_test.cc @@ -207,6 +207,9 @@ class HybridEnd2endTest : public ::testing::Test { ServerBuilder builder; builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials()); + // Always add a sync unimplemented service: we rely on having at least one + // synchronous method to get a listening cq + builder.RegisterService(&unimplemented_service_); builder.RegisterService(service1); if (service2) { builder.RegisterService(service2); @@ -216,7 +219,7 @@ class HybridEnd2endTest : public ::testing::Test { } // Create a separate cq for each potential handler. for (int i = 0; i < 5; i++) { - cqs_.push_back(builder.AddCompletionQueue()); + cqs_.push_back(builder.AddCompletionQueue(false)); } server_ = builder.BuildAndStart(); } @@ -252,6 +255,7 @@ class HybridEnd2endTest : public ::testing::Test { EchoRequest send_request; EchoResponse recv_response; ClientContext cli_ctx; + cli_ctx.set_fail_fast(false); send_request.set_message("Hello"); Status recv_status = stub_->Echo(&cli_ctx, send_request, &recv_response); EXPECT_EQ(send_request.message(), recv_response.message()); @@ -265,6 +269,7 @@ class HybridEnd2endTest : public ::testing::Test { EchoRequest send_request; EchoResponse recv_response; ClientContext cli_ctx; + cli_ctx.set_fail_fast(false); send_request.set_message("Hello"); Status recv_status = stub->Echo(&cli_ctx, send_request, &recv_response); EXPECT_EQ(send_request.message() + "_dup", recv_response.message()); @@ -276,6 +281,7 @@ class HybridEnd2endTest : public ::testing::Test { EchoResponse recv_response; grpc::string expected_message; ClientContext cli_ctx; + cli_ctx.set_fail_fast(false); send_request.set_message("Hello"); auto stream = stub_->RequestStream(&cli_ctx, &recv_response); for (int i = 0; i < 5; i++) { @@ -292,6 +298,7 @@ class HybridEnd2endTest : public ::testing::Test { EchoRequest request; EchoResponse response; ClientContext context; + context.set_fail_fast(false); request.set_message("hello"); auto stream = stub_->ResponseStream(&context, request); @@ -311,6 +318,7 @@ class HybridEnd2endTest : public ::testing::Test { EchoRequest request; EchoResponse response; ClientContext context; + context.set_fail_fast(false); grpc::string msg("hello"); auto stream = stub_->BidiStream(&context); @@ -338,6 +346,7 @@ class HybridEnd2endTest : public ::testing::Test { EXPECT_TRUE(s.ok()); } + grpc::testing::UnimplementedService::Service unimplemented_service_; std::vector<std::unique_ptr<ServerCompletionQueue> > cqs_; std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; std::unique_ptr<Server> server_; diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc index 87e3709d7d..1c1095087a 100644 --- a/test/cpp/end2end/server_builder_plugin_test.cc +++ b/test/cpp/end2end/server_builder_plugin_test.cc @@ -61,6 +61,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; } @@ -189,6 +190,7 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> { void StartServer() { grpc::string server_address = "localhost:" + to_string(port_); builder_->AddListeningPort(server_address, InsecureServerCredentials()); + cq_ = builder_->AddCompletionQueue(); server_ = builder_->BuildAndStart(); EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr); } @@ -206,6 +208,12 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> { EXPECT_TRUE(plugin != nullptr); 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)) + ; } string to_string(const int number) { @@ -218,6 +226,7 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> { std::shared_ptr<Channel> channel_; std::unique_ptr<ServerBuilder> builder_; std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; + std::unique_ptr<ServerCompletionQueue> cq_; std::unique_ptr<Server> server_; TestServiceImpl service_; int port_; diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc index c8b1e505c1..c171969e14 100644 --- a/test/cpp/interop/client_helper.cc +++ b/test/cpp/interop/client_helper.cc @@ -97,30 +97,25 @@ std::shared_ptr<Channel> CreateChannelForTestCase( snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(), FLAGS_server_port); + std::shared_ptr<CallCredentials> creds; if (test_case == "compute_engine_creds") { - std::shared_ptr<CallCredentials> creds; GPR_ASSERT(FLAGS_use_tls); creds = GoogleComputeEngineCredentials(); - return CreateTestChannel(host_port, FLAGS_server_host_override, - FLAGS_use_tls, !FLAGS_use_test_ca, creds); + GPR_ASSERT(creds); } else if (test_case == "jwt_token_creds") { - std::shared_ptr<CallCredentials> creds; GPR_ASSERT(FLAGS_use_tls); grpc::string json_key = GetServiceAccountJsonKey(); std::chrono::seconds token_lifetime = std::chrono::hours(1); creds = ServiceAccountJWTAccessCredentials(json_key, token_lifetime.count()); - return CreateTestChannel(host_port, FLAGS_server_host_override, - FLAGS_use_tls, !FLAGS_use_test_ca, creds); + GPR_ASSERT(creds); } else if (test_case == "oauth2_auth_token") { grpc::string raw_token = GetOauth2AccessToken(); - std::shared_ptr<CallCredentials> creds = AccessTokenCredentials(raw_token); - return CreateTestChannel(host_port, FLAGS_server_host_override, - FLAGS_use_tls, !FLAGS_use_test_ca, creds); - } else { - return CreateTestChannel(host_port, FLAGS_server_host_override, - FLAGS_use_tls, !FLAGS_use_test_ca); + creds = AccessTokenCredentials(raw_token); + GPR_ASSERT(creds); } + return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_use_tls, + !FLAGS_use_test_ca, creds); } } // namespace testing diff --git a/test/cpp/qps/async_streaming_ping_pong_test.cc b/test/cpp/qps/async_streaming_ping_pong_test.cc deleted file mode 100644 index 4b6bae0d5c..0000000000 --- a/test/cpp/qps/async_streaming_ping_pong_test.cc +++ /dev/null @@ -1,78 +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 <set> - -#include <grpc/support/log.h> - -#include "test/cpp/qps/driver.h" -#include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" - -namespace grpc { -namespace testing { - -static const int WARMUP = 5; -static const int BENCHMARK = 5; - -static void RunAsyncStreamingPingPong() { - gpr_log(GPR_INFO, "Running Async Streaming Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(ASYNC_CLIENT); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_async_client_threads(1); - client_config.set_rpc_type(STREAMING); - client_config.mutable_load_params()->mutable_closed_loop(); - - ServerConfig server_config; - server_config.set_server_type(ASYNC_SERVER); - server_config.set_async_server_threads(1); - - const auto result = - RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - GetReporter()->ReportQPS(*result); - GetReporter()->ReportLatency(*result); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitBenchmark(&argc, &argv, true); - - grpc::testing::RunAsyncStreamingPingPong(); - return 0; -} diff --git a/test/cpp/qps/async_unary_ping_pong_test.cc b/test/cpp/qps/async_unary_ping_pong_test.cc deleted file mode 100644 index 571a8b7300..0000000000 --- a/test/cpp/qps/async_unary_ping_pong_test.cc +++ /dev/null @@ -1,77 +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 <set> - -#include <grpc/support/log.h> - -#include "test/cpp/qps/driver.h" -#include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" - -namespace grpc { -namespace testing { - -static const int WARMUP = 5; -static const int BENCHMARK = 5; - -static void RunAsyncUnaryPingPong() { - gpr_log(GPR_INFO, "Running Async Unary Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(ASYNC_CLIENT); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_async_client_threads(1); - client_config.set_rpc_type(UNARY); - client_config.mutable_load_params()->mutable_closed_loop(); - - ServerConfig server_config; - server_config.set_server_type(ASYNC_SERVER); - server_config.set_async_server_threads(1); - - const auto result = - RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - GetReporter()->ReportQPS(*result); - GetReporter()->ReportLatency(*result); -} -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitBenchmark(&argc, &argv, true); - - grpc::testing::RunAsyncUnaryPingPong(); - return 0; -} diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 175529f01b..2a89eb8018 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -38,6 +38,7 @@ #include <mutex> #include <vector> +#include <grpc++/channel.h> #include <grpc++/support/byte_buffer.h> #include <grpc++/support/channel_arguments.h> #include <grpc++/support/slice.h> @@ -315,6 +316,10 @@ class ClientImpl : public Client { target, config.security_params().server_host_override(), config.has_security_params(), !config.security_params().use_test_ca(), std::shared_ptr<CallCredentials>(), args); + gpr_log(GPR_INFO, "Connecting to %s", target.c_str()); + GPR_ASSERT(channel_->WaitForConnected( + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(30, GPR_TIMESPAN)))); stub_ = create_stub(channel_); } Channel* get_channel() { return channel_.get(); } diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index c32160a7d4..6ad4c320b5 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> 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..57d8c22a95 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -43,7 +43,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" diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py index 6b3329b046..34b8151441 100755 --- a/test/cpp/qps/gen_build_yaml.py +++ b/test/cpp/qps/gen_build_yaml.py @@ -44,8 +44,29 @@ sys.path.append(run_tests_root) import performance.scenario_config as scenario_config def _scenario_json_string(scenario_json): + # tweak parameters to get fast test times + scenario_json['warmup_seconds'] = 1 + scenario_json['benchmark_seconds'] = 1 return json.dumps(scenario_config.remove_nonproto_fields(scenario_json)) +def threads_of_type(scenario_json, path): + d = scenario_json + for el in path.split('/'): + if el not in d: + return 0 + d = d[el] + return d + +def guess_cpu(scenario_json): + client = threads_of_type(scenario_json, 'client_config/async_client_threads') + server = threads_of_type(scenario_json, 'server_config/async_server_threads') + # make an arbitrary guess if set to auto-detect + # about the size of the jenkins instances we have for unit tests + if client == 0: client = 8 + if server == 0: server = 8 + return (scenario_json['num_clients'] * client + + scenario_json['num_servers'] * server) + print yaml.dump({ 'tests': [ { @@ -59,7 +80,7 @@ print yaml.dump({ 'language': 'c++', 'boringssl': True, 'defaults': 'boringssl', - 'cpu_cost': 1000.0, + 'cpu_cost': guess_cpu(scenario_json), 'exclude_configs': [] } for scenario_json in scenario_config.CXXLanguage().scenarios() diff --git a/test/cpp/qps/generic_async_streaming_ping_pong_test.cc b/test/cpp/qps/generic_async_streaming_ping_pong_test.cc deleted file mode 100644 index ea373ece84..0000000000 --- a/test/cpp/qps/generic_async_streaming_ping_pong_test.cc +++ /dev/null @@ -1,82 +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 <set> - -#include <grpc/support/log.h> - -#include "test/cpp/qps/driver.h" -#include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" - -namespace grpc { -namespace testing { - -static const int WARMUP = 5; -static const int BENCHMARK = 5; - -static void RunGenericAsyncStreamingPingPong() { - gpr_log(GPR_INFO, "Running Generic Async Streaming Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(ASYNC_CLIENT); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_async_client_threads(1); - client_config.set_rpc_type(STREAMING); - client_config.mutable_load_params()->mutable_closed_loop(); - auto bbuf = client_config.mutable_payload_config()->mutable_bytebuf_params(); - bbuf->set_resp_size(0); - bbuf->set_req_size(0); - - ServerConfig server_config; - server_config.set_server_type(ASYNC_GENERIC_SERVER); - server_config.set_async_server_threads(1); - *server_config.mutable_payload_config() = client_config.payload_config(); - - const auto result = - RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - GetReporter()->ReportQPS(*result); - GetReporter()->ReportLatency(*result); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitBenchmark(&argc, &argv, true); - - grpc::testing::RunGenericAsyncStreamingPingPong(); - return 0; -} diff --git a/test/cpp/qps/parse_json.cc b/test/cpp/qps/parse_json.cc index df7a62f0a0..a90bf6153c 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> diff --git a/test/cpp/qps/parse_json.h b/test/cpp/qps/parse_json.h index 4b8ca79f21..42d7d22c53 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 { 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/qps_test.cc b/test/cpp/qps/qps_test.cc index c3e72d9b17..f94ea0cb49 100644 --- a/test/cpp/qps/qps_test.cc +++ b/test/cpp/qps/qps_test.cc @@ -50,8 +50,8 @@ static void RunQPS() { ClientConfig client_config; client_config.set_client_type(ASYNC_CLIENT); - client_config.set_outstanding_rpcs_per_channel(1000); - client_config.set_client_channels(8); + client_config.set_outstanding_rpcs_per_channel(100); + client_config.set_client_channels(64); client_config.set_async_client_threads(8); client_config.set_rpc_type(STREAMING); client_config.mutable_load_params()->mutable_closed_loop(); 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 1234542687..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" @@ -131,10 +129,10 @@ class AsyncQpsServerTest : public Server { } } ~AsyncQpsServerTest() { - server_->Shutdown(); for (auto ss = shutdown_state_.begin(); ss != shutdown_state_.end(); ++ss) { (*ss)->set_shutdown(); } + server_->Shutdown(); for (auto thr = threads_.begin(); thr != threads_.end(); thr++) { thr->join(); } 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/qps/sync_streaming_ping_pong_test.cc b/test/cpp/qps/sync_streaming_ping_pong_test.cc deleted file mode 100644 index 67c62f4bae..0000000000 --- a/test/cpp/qps/sync_streaming_ping_pong_test.cc +++ /dev/null @@ -1,76 +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 <set> - -#include <grpc/support/log.h> - -#include "test/cpp/qps/driver.h" -#include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" - -namespace grpc { -namespace testing { - -static const int WARMUP = 5; -static const int BENCHMARK = 5; - -static void RunSynchronousStreamingPingPong() { - gpr_log(GPR_INFO, "Running Synchronous Streaming Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(SYNC_CLIENT); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_rpc_type(STREAMING); - client_config.mutable_load_params()->mutable_closed_loop(); - - ServerConfig server_config; - server_config.set_server_type(SYNC_SERVER); - - const auto result = - RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - GetReporter()->ReportQPS(*result); - GetReporter()->ReportLatency(*result); -} -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitBenchmark(&argc, &argv, true); - - grpc::testing::RunSynchronousStreamingPingPong(); - - return 0; -} diff --git a/test/cpp/qps/sync_unary_ping_pong_test.cc b/test/cpp/qps/sync_unary_ping_pong_test.cc deleted file mode 100644 index aa0c0c3013..0000000000 --- a/test/cpp/qps/sync_unary_ping_pong_test.cc +++ /dev/null @@ -1,77 +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 <set> - -#include <grpc/support/log.h> - -#include "test/cpp/qps/driver.h" -#include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" - -namespace grpc { -namespace testing { - -static const int WARMUP = 5; -static const int BENCHMARK = 5; - -static void RunSynchronousUnaryPingPong() { - gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong"); - - ClientConfig client_config; - client_config.set_client_type(SYNC_CLIENT); - client_config.set_outstanding_rpcs_per_channel(1); - client_config.set_client_channels(1); - client_config.set_rpc_type(UNARY); - client_config.mutable_load_params()->mutable_closed_loop(); - - ServerConfig server_config; - server_config.set_server_type(SYNC_SERVER); - - const auto result = - RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - - GetReporter()->ReportQPS(*result); - GetReporter()->ReportLatency(*result); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitBenchmark(&argc, &argv, true); - - grpc::testing::RunSynchronousUnaryPingPong(); - - return 0; -} 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/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 |