Add timeout flag to gRPC cli

Signed-off-by: Alisha Nanda <alishananda@google.com>
pull/24043/head
Alisha Nanda 4 years ago
parent e8bb9ec2af
commit 88d99b4603
  1. 9
      src/proto/grpc/testing/echo.proto
  2. 8
      src/proto/grpc/testing/simple_messages.proto
  3. 8
      test/core/util/test_config.cc
  4. 3
      test/core/util/test_config.h
  5. 3
      test/cpp/util/BUILD
  6. 10
      test/cpp/util/cli_call.cc
  7. 2
      test/cpp/util/cli_call.h
  8. 53
      test/cpp/util/cli_flags.cc
  9. 47
      test/cpp/util/cli_flags.h
  10. 32
      test/cpp/util/grpc_tool.cc
  11. 1
      test/cpp/util/grpc_tool.h
  12. 129
      test/cpp/util/grpc_tool_test.cc

@ -15,15 +15,17 @@
syntax = "proto3";
package grpc.testing;
import "src/proto/grpc/testing/echo_messages.proto";
import "src/proto/grpc/testing/simple_messages.proto";
package grpc.testing;
service EchoTestService {
rpc Echo(EchoRequest) returns (EchoResponse);
rpc Echo1(EchoRequest) returns (EchoResponse);
rpc Echo2(EchoRequest) returns (EchoResponse);
rpc CheckDeadlineUpperBound(SimpleRequest) returns (StringValue);
rpc CheckDeadlineSet(SimpleRequest) returns (StringValue);
// A service which checks that the initial metadata sent over contains some
// expected key value pair
rpc CheckClientInitialMetadata(SimpleRequest) returns (SimpleResponse);
@ -64,5 +66,4 @@ service UnimplementedEchoService {
}
// A service without any rpc defined to test coverage.
service NoRpcService {
}
service NoRpcService {}

@ -17,8 +17,10 @@ syntax = "proto3";
package grpc.testing;
message SimpleRequest {
}
message SimpleRequest {}
message SimpleResponse {}
message SimpleResponse {
message StringValue {
string message = 1;
}

@ -368,6 +368,14 @@ gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
GPR_TIMESPAN));
}
gpr_timespec grpc_timeout_microseconds_to_deadline(int64_t time_micros) {
return gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_nanos(
grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_micros,
GPR_TIMESPAN));
}
void grpc_test_init(int /*argc*/, char** /*argv*/) {
install_crash_handler();
gpr_log(GPR_DEBUG,

@ -33,6 +33,9 @@ gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s);
/* Converts a given timeout (in milliseconds) to a deadline. */
gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms);
/* Converts a given timeout (in microseconds) to a deadline. */
gpr_timespec grpc_timeout_microseconds_to_deadline(int64_t time_micros);
#if !defined(GRPC_TEST_CUSTOM_PICK_PORT) && !defined(GRPC_PORT_ISOLATED_RUNTIME)
#define GRPC_TEST_PICK_PORT
#endif

@ -122,12 +122,14 @@ grpc_cc_library(
srcs = [
"cli_call.cc",
"cli_credentials.cc",
"cli_flags.cc",
"proto_file_parser.cc",
"service_describer.cc",
],
hdrs = [
"cli_call.h",
"cli_credentials.h",
"cli_flags.h",
"config_grpc_cli.h",
"proto_file_parser.h",
"service_describer.h",
@ -141,6 +143,7 @@ grpc_cc_library(
":grpc++_proto_reflection_desc_db",
"//:grpc++",
"//src/proto/grpc/reflection/v1alpha:reflection_proto",
"//test/core/util:grpc_test_util",
],
)

@ -19,6 +19,7 @@
#include "test/cpp/util/cli_call.h"
#include <iostream>
#include <math.h>
#include <utility>
#include <grpc/grpc.h>
@ -28,6 +29,8 @@
#include <grpcpp/client_context.h>
#include <grpcpp/support/byte_buffer.h>
#include "test/core/util/test_config.h"
namespace grpc {
namespace testing {
namespace {
@ -61,6 +64,13 @@ CliCall::CliCall(const std::shared_ptr<grpc::Channel>& channel,
ctx_.AddMetadata(iter->first, iter->second);
}
}
// Set deadline if timeout > 0 (default value -1 if no timeout specified)
if (FLAGS_timeout > 0){
int64_t timeout_in_us = ceil(FLAGS_timeout * 1e6);
ctx_.set_deadline(grpc_timeout_microseconds_to_deadline(timeout_in_us));
}
call_ = stub_->PrepareCall(&ctx_, method, &cq_);
call_->StartCall(tag(1));
void* got_tag;

@ -27,6 +27,8 @@
#include <grpcpp/support/status.h>
#include <grpcpp/support/string_ref.h>
#include "test/cpp/util/cli_flags.h"
namespace grpc {
class ClientContext;

@ -0,0 +1,53 @@
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "test/cpp/util/cli_flags.h"
namespace grpc {
namespace testing {
// Define all flags used in gRPC cli.
DEFINE_bool(l, false, "Use a long listing format");
DEFINE_bool(remotedb, true, "Use server types to parse and format messages");
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.");
DEFINE_string(protofiles, "", "Name of the proto file.");
DEFINE_bool(binary_input, false, "Input in binary format");
DEFINE_bool(binary_output, false, "Output in binary format");
DEFINE_string(
default_service_config, "",
"Default service config to use on the channel, if non-empty. Note that "
"this will be ignored if the name resolver returns a service config.");
DEFINE_bool(display_peer_address, false,
"Log the peer socket address of the connection that each RPC is "
"made on to stderr.");
DEFINE_bool(json_input, false, "Input in json format");
DEFINE_bool(json_output, false, "Output in json format");
DEFINE_string(infile, "", "Input file (default is stdin)");
DEFINE_bool(batch, false,
"Input contains multiple requests. Please do not use this to send "
"more than a few RPCs. gRPC CLI has very different performance "
"characteristics compared with normal RPC calls which make it "
"unsuitable for loadtesting or significant production traffic.");
DEFINE_double(timeout, -1,
"Specify timeout in seconds, used to set the deadline for all "
"RPCs. The default value of -1 means no deadline has been set.");
} // namespace testing
} // namespace grpc

@ -0,0 +1,47 @@
/*
*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_TEST_CPP_UTIL_CLI_FLAGS_H
#define GRPC_TEST_CPP_UTIL_CLI_FLAGS_H
#include <gflags/gflags.h>
namespace grpc {
namespace testing {
// Declare all flags used in gRPC cli.
DECLARE_bool(l);
DECLARE_bool(remotedb);
DECLARE_string(metadata);
DECLARE_string(proto_path);
DECLARE_string(protofiles);
DECLARE_bool(binary_input);
DECLARE_bool(binary_output);
DECLARE_string(default_service_config);
DECLARE_bool(display_peer_address);
DECLARE_bool(json_input);
DECLARE_bool(json_output);
DECLARE_string(infile);
DECLARE_bool(batch);
DECLARE_double(timeout);
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_CLI_FLAGS_H

@ -26,7 +26,6 @@
#include <string>
#include <thread>
#include <gflags/gflags.h>
#include <grpc/grpc.h>
#include <grpc/support/port_platform.h>
#include <grpcpp/channel.h>
@ -49,32 +48,6 @@
namespace grpc {
namespace testing {
DEFINE_bool(l, false, "Use a long listing format");
DEFINE_bool(remotedb, true, "Use server types to parse and format messages");
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.");
DEFINE_string(protofiles, "", "Name of the proto file.");
DEFINE_bool(binary_input, false, "Input in binary format");
DEFINE_bool(binary_output, false, "Output in binary format");
DEFINE_string(
default_service_config, "",
"Default service config to use on the channel, if non-empty. Note "
"that this will be ignored if the name resolver returns a service "
"config.");
DEFINE_bool(
display_peer_address, false,
"Log the peer socket address of the connection that each RPC is made "
"on to stderr.");
DEFINE_bool(json_input, false, "Input in json format");
DEFINE_bool(json_output, false, "Output in json format");
DEFINE_string(infile, "", "Input file (default is stdin)");
DEFINE_bool(batch, false,
"Input contains multiple requests. Please do not use this to send "
"more than a few RPCs. gRPC CLI has very different performance "
"characteristics compared with normal RPC calls which make it "
"unsuitable for loadtesting or significant production traffic.");
namespace {
class GrpcTool {
@ -490,7 +463,10 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
" --binary_input ; Input in binary format\n"
" --binary_output ; Output in binary format\n"
" --json_input ; Input in json format\n"
" --json_output ; Output in json format\n" +
" --json_output ; Output in json format\n"
" --timeout ; Specify timeout (in seconds), used to "
"set the deadline for RPCs. The default value of -1 means no "
"deadline has been set.\n" +
cred.GetCredentialUsage());
std::stringstream output_ss;

@ -24,6 +24,7 @@
#include <grpcpp/support/config.h>
#include "test/cpp/util/cli_credentials.h"
#include "test/cpp/util/cli_flags.h"
namespace grpc {
namespace testing {

@ -18,7 +18,6 @@
#include "test/cpp/util/grpc_tool.h"
#include <gflags/gflags.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpcpp/channel.h>
@ -54,6 +53,8 @@ using grpc::testing::EchoResponse;
"Echo\n" \
"Echo1\n" \
"Echo2\n" \
"CheckDeadlineUpperBound\n" \
"CheckDeadlineSet\n" \
"CheckClientInitialMetadata\n" \
"RequestStream\n" \
"ResponseStream\n" \
@ -70,6 +71,10 @@ using grpc::testing::EchoResponse;
"{}\n" \
" rpc Echo2(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
"{}\n" \
" rpc CheckDeadlineUpperBound(grpc.testing.SimpleRequest) returns " \
"(grpc.testing.StringValue) {}\n" \
" rpc CheckDeadlineSet(grpc.testing.SimpleRequest) returns " \
"(grpc.testing.StringValue) {}\n" \
" rpc CheckClientInitialMetadata(grpc.testing.SimpleRequest) returns " \
"(grpc.testing.SimpleResponse) {}\n" \
" rpc RequestStream(stream grpc.testing.EchoRequest) returns " \
@ -109,17 +114,6 @@ DECLARE_string(ssl_target);
namespace grpc {
namespace testing {
DECLARE_bool(binary_input);
DECLARE_bool(binary_output);
DECLARE_bool(json_input);
DECLARE_bool(json_output);
DECLARE_bool(l);
DECLARE_bool(batch);
DECLARE_string(metadata);
DECLARE_string(protofiles);
DECLARE_string(proto_path);
DECLARE_string(default_service_config);
namespace {
const int kServerDefaultResponseStreamsToSend = 3;
@ -177,6 +171,30 @@ class TestServiceImpl : public ::grpc::testing::EchoTestService::Service {
return Status::OK;
}
Status CheckDeadlineSet(ServerContext* context, const SimpleRequest* request,
StringValue* response) override {
response->set_message(context->deadline() !=
std::chrono::system_clock::time_point::max()
? "true"
: "false");
return Status::OK;
}
// Check if deadline - current time <= timeout
// If deadline set, timeout + current time should be an upper bound for it
Status CheckDeadlineUpperBound(ServerContext* context,
const SimpleRequest* request,
StringValue* response) override {
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(
context->deadline() - std::chrono::system_clock::now());
// Returning string instead of bool to avoid using embedded messages in
// proto3
response->set_message(seconds.count() <= FLAGS_timeout ? "true"
: "false");
return Status::OK;
}
Status RequestStream(ServerContext* context,
ServerReader<EchoRequest>* reader,
EchoResponse* response) override {
@ -862,6 +880,93 @@ TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequestJsonInput) {
ShutdownServer();
}
TEST_F(GrpcToolTest, CallCommandWithTimeoutDeadlineSet) {
// Test input "grpc_cli call CheckDeadlineSet --timeout=5000.25"
std::stringstream output_stream;
const std::string server_address = SetUpServer();
const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
"CheckDeadlineSet"};
// Set timeout to 5000.25 seconds
FLAGS_timeout = 5000.25;
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
// Expected output: "message: "true"", deadline set
EXPECT_TRUE(nullptr !=
strstr(output_stream.str().c_str(), "message: \"true\""));
ShutdownServer();
}
TEST_F(GrpcToolTest, CallCommandWithTimeoutDeadlineUpperBound) {
// Test input "grpc_cli call CheckDeadlineUpperBound --timeout=900"
std::stringstream output_stream;
const std::string server_address = SetUpServer();
const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
"CheckDeadlineUpperBound"};
// Set timeout to 900 seconds
FLAGS_timeout = 900;
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
// Expected output: "message: "true""
// deadline not greater than timeout + current time
EXPECT_TRUE(nullptr !=
strstr(output_stream.str().c_str(), "message: \"true\""));
ShutdownServer();
}
TEST_F(GrpcToolTest, CallCommandWithNegativeTimeoutValue) {
// Test input "grpc_cli call CheckDeadlineSet --timeout=-5"
std::stringstream output_stream;
const std::string server_address = SetUpServer();
const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
"CheckDeadlineSet"};
// Set timeout to -5 (deadline not set)
FLAGS_timeout = -5;
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
// Expected output: "message: "false"", deadline not set
EXPECT_TRUE(nullptr !=
strstr(output_stream.str().c_str(), "message: \"false\""));
ShutdownServer();
}
TEST_F(GrpcToolTest, CallCommandWithDefaultTimeoutValue) {
// Test input "grpc_cli call CheckDeadlineSet --timeout=-1"
std::stringstream output_stream;
const std::string server_address = SetUpServer();
const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
"CheckDeadlineSet"};
// Set timeout to -1 (default value, deadline not set)
FLAGS_timeout = -1;
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
// Expected output: "message: "false"", deadline not set
EXPECT_TRUE(nullptr !=
strstr(output_stream.str().c_str(), "message: \"false\""));
ShutdownServer();
}
TEST_F(GrpcToolTest, CallCommandResponseStream) {
// Test input: grpc_cli call localhost:<port> ResponseStream "message:
// 'Hello'"

Loading…
Cancel
Save