Merge pull request #7269 from y-zeng/cli_call

Support server reflection in CLI
pull/7500/head
kpayson64 8 years ago committed by GitHub
commit b8208ff79a
  1. 8
      Makefile
  2. 4
      build.yaml
  3. 29
      doc/command_line_tool.md
  4. 89
      test/cpp/util/grpc_cli.cc
  5. 47
      test/cpp/util/proto_file_parser.cc
  6. 11
      test/cpp/util/proto_file_parser.h
  7. 12
      test/cpp/util/proto_reflection_descriptor_database.cc
  8. 9
      tools/run_tests/sources_and_headers.json
  9. 6
      vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
  10. 6
      vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
  11. 3
      vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj

@ -4090,6 +4090,7 @@ endif
LIBGRPC_CLI_LIBS_SRC = \ LIBGRPC_CLI_LIBS_SRC = \
test/cpp/util/cli_call.cc \ test/cpp/util/cli_call.cc \
test/cpp/util/proto_file_parser.cc \ test/cpp/util/proto_file_parser.cc \
test/cpp/util/proto_reflection_descriptor_database.cc \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
@ -10997,16 +10998,16 @@ $(BINDIR)/$(CONFIG)/grpc_cli: protobuf_dep_error
else else
$(BINDIR)/$(CONFIG)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(BINDIR)/$(CONFIG)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_cli $(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_cli
endif endif
endif endif
$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_grpc_cli: $(GRPC_CLI_OBJS:.o=.dep) deps_grpc_cli: $(GRPC_CLI_OBJS:.o=.dep)
@ -14920,6 +14921,7 @@ test/cpp/util/byte_buffer_proto_helper.cc: $(OPENSSL_DEP)
test/cpp/util/cli_call.cc: $(OPENSSL_DEP) test/cpp/util/cli_call.cc: $(OPENSSL_DEP)
test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP) test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP)
test/cpp/util/proto_file_parser.cc: $(OPENSSL_DEP) test/cpp/util/proto_file_parser.cc: $(OPENSSL_DEP)
test/cpp/util/proto_reflection_descriptor_database.cc: $(OPENSSL_DEP)
test/cpp/util/string_ref_helper.cc: $(OPENSSL_DEP) test/cpp/util/string_ref_helper.cc: $(OPENSSL_DEP)
test/cpp/util/subprocess.cc: $(OPENSSL_DEP) test/cpp/util/subprocess.cc: $(OPENSSL_DEP)
test/cpp/util/test_config.cc: $(OPENSSL_DEP) test/cpp/util/test_config.cc: $(OPENSSL_DEP)

@ -1030,10 +1030,13 @@ libs:
headers: headers:
- test/cpp/util/cli_call.h - test/cpp/util/cli_call.h
- test/cpp/util/proto_file_parser.h - test/cpp/util/proto_file_parser.h
- test/cpp/util/proto_reflection_descriptor_database.h
src: src:
- test/cpp/util/cli_call.cc - test/cpp/util/cli_call.cc
- test/cpp/util/proto_file_parser.cc - test/cpp/util/proto_file_parser.cc
- test/cpp/util/proto_reflection_descriptor_database.cc
deps: deps:
- grpc++_reflection
- grpc++ - grpc++
- grpc_plugin_support - grpc_plugin_support
- name: grpc_plugin_support - name: grpc_plugin_support
@ -2657,6 +2660,7 @@ targets:
- grpc_cli_libs - grpc_cli_libs
- grpc++_test_util - grpc++_test_util
- grpc_test_util - grpc_test_util
- grpc++_reflection
- grpc++ - grpc++
- grpc - grpc
- gpr_test_util - gpr_test_util

@ -15,6 +15,7 @@ The command line tool can do the following things:
- Send unary rpc. - Send unary rpc.
- Attach metadata and display received metadata. - Attach metadata and display received metadata.
- Handle common authentication to server. - Handle common authentication to server.
- Infer request/response types from server reflection result.
- Find the request/response types from a given proto file. - Find the request/response types from a given proto file.
- Read proto request in text form. - Read proto request in text form.
- Read request in wire form (for protobuf messages, this means serialized binary form). - Read request in wire form (for protobuf messages, this means serialized binary form).
@ -24,7 +25,6 @@ The command line tool can do the following things:
The command line tool should support the following things: The command line tool should support the following things:
- List server services and methods through server reflection. - List server services and methods through server reflection.
- Infer request/response types from server reflection result.
- Fine-grained auth control (such as, use this oauth token to talk to the server). - Fine-grained auth control (such as, use this oauth token to talk to the server).
- Send streaming rpc. - Send streaming rpc.
@ -46,24 +46,35 @@ https://github.com/grpc/grpc/blob/master/test/cpp/util/grpc_cli.cc
Send a rpc to a helloworld server at `localhost:50051`: Send a rpc to a helloworld server at `localhost:50051`:
``` ```
$ bins/opt/grpc_cli call localhost:50051 SayHello examples/protos/helloworld.proto \ $ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \
"name: 'world'" --enable_ssl=false --enable_ssl=false
``` ```
On success, the tool will print out On success, the tool will print out
``` ```
Rpc succeeded with OK status Rpc succeeded with OK status
Response: Response:
message: "Hello world" message: "Hello world"
``` ```
The `localhost:50051` part indicates the server you are connecting to. `SayHello` is (part of) the The `localhost:50051` part indicates the server you are connecting to. `SayHello` is (part of) the
gRPC method string. Then there is the path to the proto file containing the service definition, gRPC method string. Then `"name: 'world'"` is the text format of the request proto message. We are
if it is not under current directory, you can use `--proto_path` to specify a new search root. not using ssl here by `--enable_ssl=false`. For information on more flags, look at the comments of `grpc_cli.cc`.
`"name: 'world'"` is the text format of the request proto message.
We are not using ssl here by `--enable_ssl=false`. For information on more ### Use local proto files
flags, look at the comments of `grpc_cli.cc`.
If the server does not have the server reflection service, you will need to provide local proto
files containing the service definition. The tool will try to find request/response types from
them.
```
$ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \
--protofiles=examples/protos/helloworld.proto --enable_ssl=false
```
If the proto files is not under current directory, you can use `--proto_path` to specify a new
search root.
### Send non-proto rpc ### Send non-proto rpc

@ -34,18 +34,21 @@
/* /*
A command line tool to talk to a grpc server. A command line tool to talk to a grpc server.
Example of talking to grpc interop server: Example of talking to grpc interop server:
grpc_cli call localhost:50051 UnaryCall src/proto/grpc/testing/test.proto \ grpc_cli call localhost:50051 UnaryCall "response_size:10" \
"response_size:10" --enable_ssl=false --protofiles=src/proto/grpc/testing/test.proto --enable_ssl=false
Options: Options:
1. --proto_path, if your proto file is not under current working directory, 1. --protofiles, use this flag to provide a proto file if the server does
does not have the reflection service.
2. --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 use this flag to provide a search root. It should work similar to the
counterpart in protoc. counterpart in protoc. This option is valid only when protofiles is
2. --metadata specifies metadata to be sent to the server, such as: provided.
3. --metadata specifies metadata to be sent to the server, such as:
--metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2" --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
3. --enable_ssl, whether to use tls. 4. --enable_ssl, whether to use tls.
4. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call 5. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
3. --input_binary_file, a file containing the serialized request. The file 6. --input_binary_file, a file containing the serialized request. The file
can be generated by calling something like: can be generated by calling something like:
protoc --proto_path=src/proto/grpc/testing/ \ protoc --proto_path=src/proto/grpc/testing/ \
--encode=grpc.testing.SimpleRequest \ --encode=grpc.testing.SimpleRequest \
@ -53,7 +56,7 @@
< input.txt > input.bin < input.txt > input.bin
If this is used and no proto file is provided in the argument list, the 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. 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 7. --output_binary_file, a file to write binary format response into, it can
be later decoded using protoc: be later decoded using protoc:
protoc --proto_path=src/proto/grpc/testing/ \ protoc --proto_path=src/proto/grpc/testing/ \
--decode=grpc.testing.SimpleResponse \ --decode=grpc.testing.SimpleResponse \
@ -61,6 +64,7 @@
< output.bin > output.txt < output.bin > output.txt
*/ */
#include <unistd.h>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -86,6 +90,8 @@ DEFINE_string(output_binary_file, "",
DEFINE_string(metadata, "", DEFINE_string(metadata, "",
"Metadata to send to server, in the form of key1:val1:key2:val2"); "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(proto_path, ".", "Path to look for the proto file.");
// TODO(zyc): support a list of input proto files
DEFINE_string(protofiles, "", "Name of the proto file.");
void ParseMetadataFlag( void ParseMetadataFlag(
std::multimap<grpc::string, grpc::string>* client_metadata) { std::multimap<grpc::string, grpc::string>* client_metadata) {
@ -129,35 +135,61 @@ void PrintMetadata(const T& m, const grpc::string& message) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true); grpc::testing::InitTest(&argc, &argv, true);
if (argc < 4 || argc == 5 || grpc::string(argv[1]) != "call") { if (argc < 4 || grpc::string(argv[1]) != "call") {
std::cout << "Usage: grpc_cli call server_host:port method_name " std::cout << "Usage: grpc_cli call server_host:port method_name "
<< "[proto file] [text format request] [<options>]" << std::endl; << "[proto file] [text format request] [<options>]" << std::endl;
return 1;
} }
grpc::string file_name;
grpc::string request_text; grpc::string request_text;
grpc::string server_address(argv[2]); grpc::string server_address(argv[2]);
grpc::string method_name(argv[3]); grpc::string method_name(argv[3]);
std::unique_ptr<grpc::testing::ProtoFileParser> parser; std::unique_ptr<grpc::testing::ProtoFileParser> parser;
grpc::string serialized_request_proto; grpc::string serialized_request_proto;
if (argc == 6) { if (argc == 5) {
file_name = argv[4]; request_text = argv[4];
// TODO(yangg) read from stdin as well? }
request_text = argv[5];
std::shared_ptr<grpc::ChannelCredentials> creds;
if (!FLAGS_enable_ssl) {
creds = grpc::InsecureChannelCredentials();
} else {
if (FLAGS_use_auth) {
creds = grpc::GoogleDefaultCredentials();
} else {
creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
}
} }
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, creds);
if (request_text.empty() && FLAGS_input_binary_file.empty()) { if (request_text.empty() && FLAGS_input_binary_file.empty()) {
std::cout << "Missing input. Use text format input or " if (isatty(STDIN_FILENO)) {
<< "--input_binary_file for serialized request" << std::endl; std::cout << "reading request message from stdin..." << std::endl;
return 1; }
} else if (!request_text.empty()) { std::stringstream input_stream;
parser.reset(new grpc::testing::ProtoFileParser(FLAGS_proto_path, file_name, input_stream << std::cin.rdbuf();
method_name)); request_text = input_stream.str();
}
if (!request_text.empty()) {
if (!FLAGS_protofiles.empty()) {
parser.reset(new grpc::testing::ProtoFileParser(
FLAGS_proto_path, FLAGS_protofiles, method_name));
} else {
parser.reset(new grpc::testing::ProtoFileParser(channel, method_name));
}
method_name = parser->GetFullMethodName(); method_name = parser->GetFullMethodName();
if (parser->HasError()) { if (parser->HasError()) {
return 1; return 1;
} }
if (!FLAGS_input_binary_file.empty()) {
std::cout
<< "warning: request given in argv, ignoring --input_binary_file"
<< std::endl;
}
} }
if (parser) { if (parser) {
@ -175,19 +207,6 @@ int main(int argc, char** argv) {
} }
std::cout << "connecting to " << server_address << std::endl; std::cout << "connecting to " << server_address << std::endl;
std::shared_ptr<grpc::ChannelCredentials> creds;
if (!FLAGS_enable_ssl) {
creds = grpc::InsecureChannelCredentials();
} else {
if (FLAGS_use_auth) {
creds = grpc::GoogleDefaultCredentials();
} else {
creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
}
}
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, creds);
grpc::string serialized_response_proto; grpc::string serialized_response_proto;
std::multimap<grpc::string, grpc::string> client_metadata; std::multimap<grpc::string, grpc::string> client_metadata;
std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata, std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
@ -219,7 +238,7 @@ int main(int argc, char** argv) {
} }
} else { } else {
std::cout << "Rpc failed with status code " << s.error_code() std::cout << "Rpc failed with status code " << s.error_code()
<< " error message " << s.error_message() << std::endl; << ", error message: " << s.error_message() << std::endl;
} }
return 0; return 0;

@ -95,9 +95,48 @@ ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
dynamic_factory_.reset( dynamic_factory_.reset(
new google::protobuf::DynamicMessageFactory(importer_->pool())); new google::protobuf::DynamicMessageFactory(importer_->pool()));
std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
for (int i = 0; i < file_desc->service_count(); i++) {
service_desc_list.push_back(file_desc->service(i));
}
InitProtoFileParser(method, service_desc_list);
}
ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
const grpc::string& method)
: has_error_(false),
desc_db_(new grpc::ProtoReflectionDescriptorDatabase(channel)),
desc_pool_(new google::protobuf::DescriptorPool(desc_db_.get())) {
std::vector<std::string> service_list;
if (!desc_db_->GetServices(&service_list)) {
LogError(
"Failed to get services from the server, "
"it may not have the reflection service.\n"
"Please try to use the --protofiles option to provide a proto file.");
}
if (has_error_) {
return;
}
dynamic_factory_.reset(
new google::protobuf::DynamicMessageFactory(desc_pool_.get()));
std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
for (auto it = service_list.begin(); it != service_list.end(); it++) {
service_desc_list.push_back(desc_pool_->FindServiceByName(*it));
}
InitProtoFileParser(method, service_desc_list);
}
ProtoFileParser::~ProtoFileParser() {}
void ProtoFileParser::InitProtoFileParser(
const grpc::string& method,
const std::vector<const google::protobuf::ServiceDescriptor*>
service_desc_list) {
const google::protobuf::MethodDescriptor* method_descriptor = nullptr; const google::protobuf::MethodDescriptor* method_descriptor = nullptr;
for (int i = 0; !method_descriptor && i < file_desc->service_count(); i++) { for (auto it = service_desc_list.begin(); it != service_desc_list.end();
const auto* service_desc = file_desc->service(i); it++) {
const auto* service_desc = *it;
for (int j = 0; j < service_desc->method_count(); j++) { for (int j = 0; j < service_desc->method_count(); j++) {
const auto* method_desc = service_desc->method(j); const auto* method_desc = service_desc->method(j);
if (MethodNameMatch(method_desc->full_name(), method)) { if (MethodNameMatch(method_desc->full_name(), method)) {
@ -130,8 +169,6 @@ ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
dynamic_factory_->GetPrototype(method_descriptor->output_type())->New()); dynamic_factory_->GetPrototype(method_descriptor->output_type())->New());
} }
ProtoFileParser::~ProtoFileParser() {}
grpc::string ProtoFileParser::GetSerializedProto( grpc::string ProtoFileParser::GetSerializedProto(
const grpc::string& text_format_proto, bool is_request) { const grpc::string& text_format_proto, bool is_request) {
grpc::string serialized; grpc::string serialized;
@ -143,7 +180,7 @@ grpc::string ProtoFileParser::GetSerializedProto(
LogError("Failed to parse text format to proto."); LogError("Failed to parse text format to proto.");
return ""; return "";
} }
ok = request_prototype_->SerializeToString(&serialized); ok = msg->SerializeToString(&serialized);
if (!ok) { if (!ok) {
LogError("Failed to serialize proto."); LogError("Failed to serialize proto.");
return ""; return "";

@ -38,8 +38,10 @@
#include <google/protobuf/compiler/importer.h> #include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h> #include <google/protobuf/dynamic_message.h>
#include <grpc++/channel.h>
#include "src/compiler/config.h" #include "src/compiler/config.h"
#include "test/cpp/util/proto_reflection_descriptor_database.h"
namespace grpc { namespace grpc {
namespace testing { namespace testing {
@ -53,6 +55,9 @@ class ProtoFileParser {
// even just Method. It will log an error if there is ambiguity. // even just Method. It will log an error if there is ambiguity.
ProtoFileParser(const grpc::string& proto_path, const grpc::string& file_name, ProtoFileParser(const grpc::string& proto_path, const grpc::string& file_name,
const grpc::string& method); const grpc::string& method);
ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
const grpc::string& method);
~ProtoFileParser(); ~ProtoFileParser();
grpc::string GetFullMethodName() const { return full_method_name_; } grpc::string GetFullMethodName() const { return full_method_name_; }
@ -68,12 +73,18 @@ class ProtoFileParser {
void LogError(const grpc::string& error_msg); void LogError(const grpc::string& error_msg);
private: private:
void InitProtoFileParser(
const grpc::string& method,
const std::vector<const google::protobuf::ServiceDescriptor*> services);
bool has_error_; bool has_error_;
grpc::string request_text_; grpc::string request_text_;
grpc::string full_method_name_; grpc::string full_method_name_;
google::protobuf::compiler::DiskSourceTree source_tree_; google::protobuf::compiler::DiskSourceTree source_tree_;
std::unique_ptr<ErrorPrinter> error_printer_; std::unique_ptr<ErrorPrinter> error_printer_;
std::unique_ptr<google::protobuf::compiler::Importer> importer_; std::unique_ptr<google::protobuf::compiler::Importer> importer_;
std::unique_ptr<grpc::ProtoReflectionDescriptorDatabase> desc_db_;
std::unique_ptr<google::protobuf::DescriptorPool> desc_pool_;
std::unique_ptr<google::protobuf::DynamicMessageFactory> dynamic_factory_; std::unique_ptr<google::protobuf::DynamicMessageFactory> dynamic_factory_;
std::unique_ptr<grpc::protobuf::Message> request_prototype_; std::unique_ptr<grpc::protobuf::Message> request_prototype_;
std::unique_ptr<grpc::protobuf::Message> response_prototype_; std::unique_ptr<grpc::protobuf::Message> response_prototype_;

@ -53,7 +53,17 @@ ProtoReflectionDescriptorDatabase::ProtoReflectionDescriptorDatabase(
std::shared_ptr<grpc::Channel> channel) std::shared_ptr<grpc::Channel> channel)
: stub_(ServerReflection::NewStub(channel)) {} : stub_(ServerReflection::NewStub(channel)) {}
ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {} ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {
if (stream_) {
stream_->WritesDone();
Status status = stream_->Finish();
if (!status.ok()) {
gpr_log(GPR_ERROR,
"ServerReflectionInfo rpc failed. Error code: %d, details: %s",
(int)status.error_code(), status.error_message().c_str());
}
}
}
bool ProtoReflectionDescriptorDatabase::FindFileByName( bool ProtoReflectionDescriptorDatabase::FindFileByName(
const string& filename, google::protobuf::FileDescriptorProto* output) { const string& filename, google::protobuf::FileDescriptorProto* output) {

@ -2133,6 +2133,7 @@
"gpr_test_util", "gpr_test_util",
"grpc", "grpc",
"grpc++", "grpc++",
"grpc++_reflection",
"grpc++_test_config", "grpc++_test_config",
"grpc++_test_util", "grpc++_test_util",
"grpc_cli_libs", "grpc_cli_libs",
@ -4460,11 +4461,13 @@
{ {
"deps": [ "deps": [
"grpc++", "grpc++",
"grpc++_reflection",
"grpc_plugin_support" "grpc_plugin_support"
], ],
"headers": [ "headers": [
"test/cpp/util/cli_call.h", "test/cpp/util/cli_call.h",
"test/cpp/util/proto_file_parser.h" "test/cpp/util/proto_file_parser.h",
"test/cpp/util/proto_reflection_descriptor_database.h"
], ],
"language": "c++", "language": "c++",
"name": "grpc_cli_libs", "name": "grpc_cli_libs",
@ -4472,7 +4475,9 @@
"test/cpp/util/cli_call.cc", "test/cpp/util/cli_call.cc",
"test/cpp/util/cli_call.h", "test/cpp/util/cli_call.h",
"test/cpp/util/proto_file_parser.cc", "test/cpp/util/proto_file_parser.cc",
"test/cpp/util/proto_file_parser.h" "test/cpp/util/proto_file_parser.h",
"test/cpp/util/proto_reflection_descriptor_database.cc",
"test/cpp/util/proto_reflection_descriptor_database.h"
], ],
"third_party": false, "third_party": false,
"type": "lib" "type": "lib"

@ -149,14 +149,20 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h" /> <ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h" /> <ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc"> <ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc"> <ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.cc">
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj">
<Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj"> <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project> <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
</ProjectReference> </ProjectReference>

@ -7,6 +7,9 @@
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc"> <ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
<Filter>test\cpp\util</Filter> <Filter>test\cpp\util</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h"> <ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h">
@ -15,6 +18,9 @@
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h"> <ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h">
<Filter>test\cpp\util</Filter> <Filter>test\cpp\util</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -173,6 +173,9 @@
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj"> <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project> <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj">
<Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj"> <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project> <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
</ProjectReference> </ProjectReference>

Loading…
Cancel
Save