[reflection] Add v1 reflection (#34535)

pull/34589/head
Eugene Ostroukhov 2 years ago committed by GitHub
parent 3b40af376e
commit 5817f0f6c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      BUILD
  2. 7
      CMakeLists.txt
  3. 1
      build_autogenerated.yaml
  4. 1
      grpc.gyp
  5. 8
      include/grpcpp/ext/proto_server_reflection_plugin.h
  6. 116
      src/cpp/ext/proto_server_reflection.cc
  7. 104
      src/cpp/ext/proto_server_reflection.h
  8. 30
      src/cpp/ext/proto_server_reflection_plugin.cc
  9. 80
      test/cpp/end2end/proto_server_reflection_test.cc
  10. 26
      test/cpp/util/grpc_tool_test.cc

@ -2108,6 +2108,7 @@ grpc_cc_library(
deps = [ deps = [
"grpc++", "grpc++",
"grpc++_config_proto", "grpc++_config_proto",
"//src/proto/grpc/reflection/v1:reflection_proto",
"//src/proto/grpc/reflection/v1alpha:reflection_proto", "//src/proto/grpc/reflection/v1alpha:reflection_proto",
], ],
alwayslink = 1, alwayslink = 1,

7
CMakeLists.txt generated

@ -624,6 +624,9 @@ protobuf_generate_grpc_cpp_with_import_path_correction(
protobuf_generate_grpc_cpp_with_import_path_correction( protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/lookup/v1/rls_config.proto src/proto/grpc/lookup/v1/rls_config.proto src/proto/grpc/lookup/v1/rls_config.proto src/proto/grpc/lookup/v1/rls_config.proto
) )
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/reflection/v1/reflection.proto src/proto/grpc/reflection/v1/reflection.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction( protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/reflection/v1alpha/reflection.proto src/proto/grpc/reflection/v1alpha/reflection.proto src/proto/grpc/reflection/v1alpha/reflection.proto src/proto/grpc/reflection/v1alpha/reflection.proto
) )
@ -4279,6 +4282,10 @@ endif()
if(gRPC_BUILD_CODEGEN) if(gRPC_BUILD_CODEGEN)
add_library(grpc++_reflection add_library(grpc++_reflection
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1/reflection.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1/reflection.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1/reflection.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1/reflection.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h

@ -3673,6 +3673,7 @@ libs:
headers: headers:
- src/cpp/ext/proto_server_reflection.h - src/cpp/ext/proto_server_reflection.h
src: src:
- src/proto/grpc/reflection/v1/reflection.proto
- src/proto/grpc/reflection/v1alpha/reflection.proto - src/proto/grpc/reflection/v1alpha/reflection.proto
- src/cpp/ext/proto_server_reflection.cc - src/cpp/ext/proto_server_reflection.cc
- src/cpp/ext/proto_server_reflection_plugin.cc - src/cpp/ext/proto_server_reflection_plugin.cc

1
grpc.gyp generated

@ -1842,6 +1842,7 @@
'grpc++', 'grpc++',
], ],
'sources': [ 'sources': [
'src/proto/grpc/reflection/v1/reflection.proto',
'src/proto/grpc/reflection/v1alpha/reflection.proto', 'src/proto/grpc/reflection/v1alpha/reflection.proto',
'src/cpp/ext/proto_server_reflection.cc', 'src/cpp/ext/proto_server_reflection.cc',
'src/cpp/ext/proto_server_reflection_plugin.cc', 'src/cpp/ext/proto_server_reflection_plugin.cc',

@ -19,11 +19,15 @@
#ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H
#define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H
#include <memory>
#include <grpcpp/impl/server_builder_plugin.h> #include <grpcpp/impl/server_builder_plugin.h>
#include <grpcpp/support/config.h> #include <grpcpp/support/config.h>
namespace grpc { namespace grpc {
class ProtoServerReflection; class ProtoServerReflection;
class ProtoServerReflectionBackend;
class ProtoServerReflectionV1;
class ServerInitializer; class ServerInitializer;
namespace reflection { namespace reflection {
@ -39,7 +43,9 @@ class ProtoServerReflectionPlugin : public grpc::ServerBuilderPlugin {
bool has_sync_methods() const override; bool has_sync_methods() const override;
private: private:
std::shared_ptr<grpc::ProtoServerReflection> reflection_service_; std::shared_ptr<grpc::ProtoServerReflectionBackend> backend_;
std::shared_ptr<grpc::ProtoServerReflection> reflection_service_v1alpha_;
std::shared_ptr<grpc::ProtoServerReflectionV1> reflection_service_v1_;
}; };
/// Add proto reflection plugin to \a ServerBuilder. /// Add proto reflection plugin to \a ServerBuilder.

@ -23,58 +23,41 @@
#include <grpcpp/grpcpp.h> #include <grpcpp/grpcpp.h>
#include <grpcpp/support/interceptor.h> #include <grpcpp/support/interceptor.h>
#include <grpcpp/support/sync_stream.h>
// IWYU pragma: no_include "google/protobuf/descriptor.h" // IWYU pragma: no_include "google/protobuf/descriptor.h"
// IWYU pragma: no_include <google/protobuf/descriptor.h> // IWYU pragma: no_include <google/protobuf/descriptor.h>
// IWYU pragma: no_include "src/proto/grpc/reflection/v1/reflection.pb.h"
using grpc::reflection::v1alpha::ErrorResponse; // IWYU pragma: no_include "src/proto/grpc/reflection/v1alpha/reflection.pb.h"
using grpc::reflection::v1alpha::ExtensionNumberResponse;
using grpc::reflection::v1alpha::ExtensionRequest;
using grpc::reflection::v1alpha::ListServiceResponse;
using grpc::reflection::v1alpha::ServerReflectionRequest;
using grpc::reflection::v1alpha::ServerReflectionResponse;
using grpc::reflection::v1alpha::ServiceResponse;
namespace grpc { namespace grpc {
ProtoServerReflection::ProtoServerReflection() template <typename Request, typename Response>
: descriptor_pool_(protobuf::DescriptorPool::generated_pool()) {} Status ProtoServerReflectionBackend::ServerReflectionInfo(
ServerReaderWriter<Response, Request>* stream) const {
void ProtoServerReflection::SetServiceList( Request request;
const std::vector<std::string>* services) { Response response;
services_ = services;
}
Status ProtoServerReflection::ServerReflectionInfo(
ServerContext* context,
ServerReaderWriter<ServerReflectionResponse, ServerReflectionRequest>*
stream) {
ServerReflectionRequest request;
ServerReflectionResponse response;
Status status; Status status;
while (stream->Read(&request)) { while (stream->Read(&request)) {
switch (request.message_request_case()) { switch (request.message_request_case()) {
case ServerReflectionRequest::MessageRequestCase::kFileByFilename: case Request::MessageRequestCase::kFileByFilename:
status = GetFileByName(context, request.file_by_filename(), &response); status = GetFileByName(request.file_by_filename(), &response);
break; break;
case ServerReflectionRequest::MessageRequestCase::kFileContainingSymbol: case Request::MessageRequestCase::kFileContainingSymbol:
status = GetFileContainingSymbol( status = GetFileContainingSymbol(request.file_containing_symbol(),
context, request.file_containing_symbol(), &response); &response);
break; break;
case ServerReflectionRequest::MessageRequestCase:: case Request::MessageRequestCase::kFileContainingExtension:
kFileContainingExtension:
status = GetFileContainingExtension( status = GetFileContainingExtension(
context, &request.file_containing_extension(), &response); &request.file_containing_extension(), &response);
break; break;
case ServerReflectionRequest::MessageRequestCase:: case Request::MessageRequestCase::kAllExtensionNumbersOfType:
kAllExtensionNumbersOfType:
status = GetAllExtensionNumbers( status = GetAllExtensionNumbers(
context, request.all_extension_numbers_of_type(), request.all_extension_numbers_of_type(),
response.mutable_all_extension_numbers_response()); response.mutable_all_extension_numbers_response());
break; break;
case ServerReflectionRequest::MessageRequestCase::kListServices: case Request::MessageRequestCase::kListServices:
status = status = ListService(response.mutable_list_services_response());
ListService(context, response.mutable_list_services_response());
break; break;
default: default:
status = Status(StatusCode::UNIMPLEMENTED, ""); status = Status(StatusCode::UNIMPLEMENTED, "");
@ -84,35 +67,34 @@ Status ProtoServerReflection::ServerReflectionInfo(
FillErrorResponse(status, response.mutable_error_response()); FillErrorResponse(status, response.mutable_error_response());
} }
response.set_valid_host(request.host()); response.set_valid_host(request.host());
response.set_allocated_original_request( response.set_allocated_original_request(new Request(request));
new ServerReflectionRequest(request));
stream->Write(response); stream->Write(response);
} }
return Status::OK; return Status::OK;
} }
void ProtoServerReflection::FillErrorResponse(const Status& status, template <typename Response>
ErrorResponse* error_response) { void ProtoServerReflectionBackend::FillErrorResponse(
const Status& status, Response* error_response) const {
error_response->set_error_code(status.error_code()); error_response->set_error_code(status.error_code());
error_response->set_error_message(status.error_message()); error_response->set_error_message(status.error_message());
} }
Status ProtoServerReflection::ListService(ServerContext* /*context*/, template <typename Response>
ListServiceResponse* response) { Status ProtoServerReflectionBackend::ListService(Response* response) const {
if (services_ == nullptr) { if (services_ == nullptr) {
return Status(StatusCode::NOT_FOUND, "Services not found."); return Status(StatusCode::NOT_FOUND, "Services not found.");
} }
for (const auto& value : *services_) { for (const auto& value : *services_) {
ServiceResponse* service_response = response->add_service(); auto* service_response = response->add_service();
service_response->set_name(value); service_response->set_name(value);
} }
return Status::OK; return Status::OK;
} }
Status ProtoServerReflection::GetFileByName( template <typename Response>
ServerContext* /*context*/, const std::string& file_name, Status ProtoServerReflectionBackend::GetFileByName(const std::string& file_name,
ServerReflectionResponse* response) { Response* response) const {
if (descriptor_pool_ == nullptr) { if (descriptor_pool_ == nullptr) {
return Status::CANCELLED; return Status::CANCELLED;
} }
@ -127,9 +109,9 @@ Status ProtoServerReflection::GetFileByName(
return Status::OK; return Status::OK;
} }
Status ProtoServerReflection::GetFileContainingSymbol( template <typename Response>
ServerContext* /*context*/, const std::string& symbol, Status ProtoServerReflectionBackend::GetFileContainingSymbol(
ServerReflectionResponse* response) { const std::string& symbol, Response* response) const {
if (descriptor_pool_ == nullptr) { if (descriptor_pool_ == nullptr) {
return Status::CANCELLED; return Status::CANCELLED;
} }
@ -144,9 +126,9 @@ Status ProtoServerReflection::GetFileContainingSymbol(
return Status::OK; return Status::OK;
} }
Status ProtoServerReflection::GetFileContainingExtension( template <typename Request, typename Response>
ServerContext* /*context*/, const ExtensionRequest* request, Status ProtoServerReflectionBackend::GetFileContainingExtension(
ServerReflectionResponse* response) { const Request* request, Response* response) const {
if (descriptor_pool_ == nullptr) { if (descriptor_pool_ == nullptr) {
return Status::CANCELLED; return Status::CANCELLED;
} }
@ -168,9 +150,9 @@ Status ProtoServerReflection::GetFileContainingExtension(
return Status::OK; return Status::OK;
} }
Status ProtoServerReflection::GetAllExtensionNumbers( template <typename Response>
ServerContext* /*context*/, const std::string& type, Status ProtoServerReflectionBackend::GetAllExtensionNumbers(
ExtensionNumberResponse* response) { const std::string& type, Response* response) const {
if (descriptor_pool_ == nullptr) { if (descriptor_pool_ == nullptr) {
return Status::CANCELLED; return Status::CANCELLED;
} }
@ -190,10 +172,10 @@ Status ProtoServerReflection::GetAllExtensionNumbers(
return Status::OK; return Status::OK;
} }
void ProtoServerReflection::FillFileDescriptorResponse( template <typename Response>
const protobuf::FileDescriptor* file_desc, void ProtoServerReflectionBackend::FillFileDescriptorResponse(
ServerReflectionResponse* response, const protobuf::FileDescriptor* file_desc, Response* response,
std::unordered_set<std::string>* seen_files) { std::unordered_set<std::string>* seen_files) const {
if (seen_files->find(file_desc->name()) != seen_files->end()) { if (seen_files->find(file_desc->name()) != seen_files->end()) {
return; return;
} }
@ -210,4 +192,18 @@ void ProtoServerReflection::FillFileDescriptorResponse(
} }
} }
Status ProtoServerReflection::ServerReflectionInfo(
ServerContext* /* context */,
ServerReaderWriter<reflection::v1alpha::ServerReflectionResponse,
reflection::v1alpha::ServerReflectionRequest>* stream) {
return backend_->ServerReflectionInfo(stream);
}
Status ProtoServerReflectionV1::ServerReflectionInfo(
ServerContext* /* context */,
ServerReaderWriter<reflection::v1::ServerReflectionResponse,
reflection::v1::ServerReflectionRequest>* stream) {
return backend_->ServerReflectionInfo(stream);
}
} // namespace grpc } // namespace grpc

@ -19,8 +19,10 @@
#ifndef GRPC_SRC_CPP_EXT_PROTO_SERVER_REFLECTION_H #ifndef GRPC_SRC_CPP_EXT_PROTO_SERVER_REFLECTION_H
#define GRPC_SRC_CPP_EXT_PROTO_SERVER_REFLECTION_H #define GRPC_SRC_CPP_EXT_PROTO_SERVER_REFLECTION_H
#include <memory>
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include <utility>
#include <vector> #include <vector>
#include <grpcpp/grpcpp.h> #include <grpcpp/grpcpp.h>
@ -29,18 +31,72 @@
#include <grpcpp/support/status.h> #include <grpcpp/support/status.h>
#include <grpcpp/support/sync_stream.h> #include <grpcpp/support/sync_stream.h>
#include "src/proto/grpc/reflection/v1/reflection.grpc.pb.h"
#include "src/proto/grpc/reflection/v1/reflection.pb.h"
#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h" #include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h"
#include "src/proto/grpc/reflection/v1alpha/reflection.pb.h" #include "src/proto/grpc/reflection/v1alpha/reflection.pb.h"
namespace grpc { namespace grpc {
class ProtoServerReflectionBackend {
public:
ProtoServerReflectionBackend()
: descriptor_pool_(protobuf::DescriptorPool::generated_pool()) {}
void SetServiceList(const std::vector<std::string>* services) {
services_ = services;
}
template <typename Request, typename Response>
Status ServerReflectionInfo(
ServerReaderWriter<Response, Request>* stream) const;
private:
template <typename Response>
Status ListService(Response* response) const;
template <typename Response>
Status GetFileByName(const std::string& file_name, Response* response) const;
template <typename Response>
Status GetFileContainingSymbol(const std::string& symbol,
Response* response) const;
template <typename Request, typename Response>
Status GetFileContainingExtension(const Request* request,
Response* response) const;
template <typename Response>
Status GetAllExtensionNumbers(const std::string& type,
Response* response) const;
template <typename Response>
void FillFileDescriptorResponse(
const protobuf::FileDescriptor* file_desc, Response* response,
std::unordered_set<std::string>* seen_files) const;
template <typename Response>
void FillErrorResponse(const Status& status, Response* error_response) const;
const protobuf::DescriptorPool* descriptor_pool_;
const std::vector<string>* services_;
};
class ProtoServerReflection final class ProtoServerReflection final
: public reflection::v1alpha::ServerReflection::Service { : public reflection::v1alpha::ServerReflection::Service {
public: public:
ProtoServerReflection(); ProtoServerReflection()
: grpc::ProtoServerReflection(
std::make_shared<ProtoServerReflectionBackend>()) {}
explicit ProtoServerReflection(
std::shared_ptr<ProtoServerReflectionBackend> backend)
: backend_(std::move(backend)) {}
// Add the full names of registered services // Add the full names of registered services
void SetServiceList(const std::vector<std::string>* services); void SetServiceList(const std::vector<std::string>* services) {
backend_->SetServiceList(services);
}
// implementation of ServerReflectionInfo(stream ServerReflectionRequest) rpc // implementation of ServerReflectionInfo(stream ServerReflectionRequest) rpc
// in ServerReflection service // in ServerReflection service
@ -50,36 +106,26 @@ class ProtoServerReflection final
reflection::v1alpha::ServerReflectionRequest>* stream) reflection::v1alpha::ServerReflectionRequest>* stream)
override; override;
private: std::shared_ptr<ProtoServerReflectionBackend> backend_;
Status ListService(ServerContext* context, };
reflection::v1alpha::ListServiceResponse* response);
Status GetFileByName(ServerContext* context, const std::string& file_name,
reflection::v1alpha::ServerReflectionResponse* response);
Status GetFileContainingSymbol(
ServerContext* context, const std::string& symbol,
reflection::v1alpha::ServerReflectionResponse* response);
Status GetFileContainingExtension(
ServerContext* context,
const reflection::v1alpha::ExtensionRequest* request,
reflection::v1alpha::ServerReflectionResponse* response);
Status GetAllExtensionNumbers(
ServerContext* context, const std::string& type,
reflection::v1alpha::ExtensionNumberResponse* response);
void FillFileDescriptorResponse( class ProtoServerReflectionV1 final
const protobuf::FileDescriptor* file_desc, : public reflection::v1::ServerReflection::Service {
reflection::v1alpha::ServerReflectionResponse* response, public:
std::unordered_set<std::string>* seen_files); explicit ProtoServerReflectionV1(
std::shared_ptr<ProtoServerReflectionBackend> backend)
: backend_(std::move(backend)) {}
void FillErrorResponse(const Status& status, // implementation of ServerReflectionInfo(stream ServerReflectionRequest) rpc
reflection::v1alpha::ErrorResponse* error_response); // in ServerReflection service
Status ServerReflectionInfo(
ServerContext* /* context */,
ServerReaderWriter<reflection::v1::ServerReflectionResponse,
reflection::v1::ServerReflectionRequest>* stream)
override;
const protobuf::DescriptorPool* descriptor_pool_; private:
const std::vector<string>* services_; std::shared_ptr<ProtoServerReflectionBackend> backend_;
}; };
} // namespace grpc } // namespace grpc

@ -16,6 +16,9 @@
// //
// //
#include <memory>
#include <string>
#include <grpcpp/ext/proto_server_reflection_plugin.h> #include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/impl/server_builder_plugin.h> #include <grpcpp/impl/server_builder_plugin.h>
#include <grpcpp/impl/server_initializer.h> #include <grpcpp/impl/server_initializer.h>
@ -27,35 +30,40 @@ namespace grpc {
namespace reflection { namespace reflection {
ProtoServerReflectionPlugin::ProtoServerReflectionPlugin() ProtoServerReflectionPlugin::ProtoServerReflectionPlugin()
: reflection_service_(new grpc::ProtoServerReflection()) {} : backend_(std::make_shared<ProtoServerReflectionBackend>()),
reflection_service_v1alpha_(
std::make_shared<ProtoServerReflection>(backend_)),
reflection_service_v1_(
std::make_shared<ProtoServerReflectionV1>(backend_)) {}
std::string ProtoServerReflectionPlugin::name() { std::string ProtoServerReflectionPlugin::name() {
return "proto_server_reflection"; return "proto_server_reflection";
} }
void ProtoServerReflectionPlugin::InitServer(grpc::ServerInitializer* si) { void ProtoServerReflectionPlugin::InitServer(grpc::ServerInitializer* si) {
si->RegisterService(reflection_service_); si->RegisterService(reflection_service_v1_);
si->RegisterService(reflection_service_v1alpha_);
} }
void ProtoServerReflectionPlugin::Finish(grpc::ServerInitializer* si) { void ProtoServerReflectionPlugin::Finish(grpc::ServerInitializer* si) {
reflection_service_->SetServiceList(si->GetServiceList()); backend_->SetServiceList(si->GetServiceList());
} }
void ProtoServerReflectionPlugin::ChangeArguments(const std::string& /*name*/, void ProtoServerReflectionPlugin::ChangeArguments(const std::string& /*name*/,
void* /*value*/) {} void* /*value*/) {}
bool ProtoServerReflectionPlugin::has_sync_methods() const { bool ProtoServerReflectionPlugin::has_sync_methods() const {
if (reflection_service_) { return (reflection_service_v1_ &&
return reflection_service_->has_synchronous_methods(); reflection_service_v1_->has_synchronous_methods()) ||
} (reflection_service_v1alpha_ &&
return false; reflection_service_v1alpha_->has_synchronous_methods());
} }
bool ProtoServerReflectionPlugin::has_async_methods() const { bool ProtoServerReflectionPlugin::has_async_methods() const {
if (reflection_service_) { return (reflection_service_v1_ &&
return reflection_service_->has_async_methods(); reflection_service_v1_->has_async_methods()) ||
} (reflection_service_v1alpha_ &&
return false; reflection_service_v1alpha_->has_async_methods());
} }
static std::unique_ptr<grpc::ServerBuilderPlugin> CreateProtoReflection() { static std::unique_ptr<grpc::ServerBuilderPlugin> CreateProtoReflection() {

@ -16,9 +16,11 @@
// //
// //
#include <gtest/gtest.h> #include <memory>
#include <vector>
#include "absl/memory/memory.h" #include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpcpp/channel.h> #include <grpcpp/channel.h>
@ -31,10 +33,13 @@
#include <grpcpp/server_builder.h> #include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h> #include <grpcpp/server_context.h>
#include "src/proto/grpc/reflection/v1/reflection.grpc.pb.h"
#include "src/proto/grpc/reflection/v1/reflection.pb.h"
#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h"
#include "src/proto/grpc/reflection/v1alpha/reflection.pb.h"
#include "src/proto/grpc/testing/echo.grpc.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
#include "test/cpp/end2end/test_service_impl.h"
#include "test/cpp/util/proto_reflection_descriptor_database.h" #include "test/cpp/util/proto_reflection_descriptor_database.h"
namespace grpc { namespace grpc {
@ -56,10 +61,9 @@ class ProtoServerReflectionTest : public ::testing::Test {
void ResetStub() { void ResetStub() {
string target = "dns:localhost:" + to_string(port_); string target = "dns:localhost:" + to_string(port_);
std::shared_ptr<Channel> channel = channel_ = grpc::CreateChannel(target, InsecureChannelCredentials());
grpc::CreateChannel(target, InsecureChannelCredentials()); stub_ = grpc::testing::EchoTestService::NewStub(channel_);
stub_ = grpc::testing::EchoTestService::NewStub(channel); desc_db_ = std::make_unique<ProtoReflectionDescriptorDatabase>(channel_);
desc_db_ = std::make_unique<ProtoReflectionDescriptorDatabase>(channel);
desc_pool_ = std::make_unique<protobuf::DescriptorPool>(desc_db_.get()); desc_pool_ = std::make_unique<protobuf::DescriptorPool>(desc_db_.get());
} }
@ -117,8 +121,18 @@ class ProtoServerReflectionTest : public ::testing::Test {
EXPECT_EQ(desc->DebugString(), ref_desc->DebugString()); EXPECT_EQ(desc->DebugString(), ref_desc->DebugString());
} }
template <typename Response>
std::vector<std::string> ServicesFromResponse(const Response& response) {
std::vector<std::string> services;
for (const auto& service : response.list_services_response().service()) {
services.emplace_back(service.name());
}
return services;
}
protected: protected:
std::unique_ptr<Server> server_; std::unique_ptr<Server> server_;
std::shared_ptr<Channel> channel_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<ProtoReflectionDescriptorDatabase> desc_db_; std::unique_ptr<ProtoReflectionDescriptorDatabase> desc_db_;
std::unique_ptr<protobuf::DescriptorPool> desc_pool_; std::unique_ptr<protobuf::DescriptorPool> desc_pool_;
@ -142,6 +156,58 @@ TEST_F(ProtoServerReflectionTest, CheckResponseWithLocalDescriptorPool) {
} }
} }
TEST_F(ProtoServerReflectionTest, V1AlphaApiInstalled) {
ResetStub();
using Service = reflection::v1alpha::ServerReflection;
using Request = reflection::v1alpha::ServerReflectionRequest;
using Response = reflection::v1alpha::ServerReflectionResponse;
Service::Stub stub(channel_);
ClientContext context;
auto reader_writer = stub.ServerReflectionInfo(&context);
Request request;
request.set_list_services("*");
reader_writer->Write(request);
Response response;
ASSERT_EQ(reader_writer->Read(&response), true);
EXPECT_THAT(ServicesFromResponse(response),
::testing::UnorderedElementsAre(
reflection::v1alpha::ServerReflection::service_full_name(),
reflection::v1::ServerReflection::service_full_name()));
request = Request::default_instance();
request.set_file_containing_symbol(Service::service_full_name());
reader_writer->WriteLast(request, WriteOptions());
response = Response::default_instance();
ASSERT_EQ(reader_writer->Read(&response), true);
EXPECT_EQ(response.file_descriptor_response().file_descriptor_proto_size(), 1)
<< response.DebugString();
}
TEST_F(ProtoServerReflectionTest, V1ApiInstalled) {
ResetStub();
using Service = reflection::v1::ServerReflection;
using Request = reflection::v1::ServerReflectionRequest;
using Response = reflection::v1::ServerReflectionResponse;
Service::Stub stub(channel_);
ClientContext context;
auto reader_writer = stub.ServerReflectionInfo(&context);
Request request;
request.set_list_services("*");
reader_writer->Write(request);
Response response;
ASSERT_TRUE(reader_writer->Read(&response));
EXPECT_THAT(ServicesFromResponse(response),
::testing::UnorderedElementsAre(
reflection::v1alpha::ServerReflection::service_full_name(),
reflection::v1::ServerReflection::service_full_name()));
request = Request::default_instance();
request.set_file_containing_symbol(Service::service_full_name());
reader_writer->WriteLast(request, WriteOptions());
response = Response::default_instance();
ASSERT_TRUE(reader_writer->Read(&response));
EXPECT_EQ(response.file_descriptor_response().file_descriptor_proto_size(), 1)
<< response.DebugString();
}
} // namespace testing } // namespace testing
} // namespace grpc } // namespace grpc

@ -21,10 +21,12 @@
#include <chrono> #include <chrono>
#include <sstream> #include <sstream>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "absl/flags/declare.h" #include "absl/flags/declare.h"
#include "absl/flags/flag.h" #include "absl/flags/flag.h"
#include "absl/strings/str_split.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -384,9 +386,11 @@ TEST_F(GrpcToolTest, ListCommand) {
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(), EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream, std::bind(PrintStream, &output_stream,
std::placeholders::_1))); std::placeholders::_1)));
EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), EXPECT_THAT(absl::StrSplit(output_stream.str(), "\n"),
"grpc.testing.EchoTestService\n" ::testing::UnorderedElementsAre(
"grpc.reflection.v1alpha.ServerReflection\n")); "grpc.testing.EchoTestService",
"grpc.reflection.v1alpha.ServerReflection",
"grpc.reflection.v1.ServerReflection", ""));
ShutdownServer(); ShutdownServer();
} }
@ -1395,9 +1399,11 @@ TEST_F(GrpcToolTest, ListCommandOverrideSslHostName) {
0 == GrpcToolMainLib( 0 == GrpcToolMainLib(
ArraySize(argv), argv, TestCliCredentials(true), ArraySize(argv), argv, TestCliCredentials(true),
std::bind(PrintStream, &output_stream, std::placeholders::_1))); std::bind(PrintStream, &output_stream, std::placeholders::_1)));
EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), EXPECT_THAT(
"grpc.testing.EchoTestService\n" absl::StrSplit(output_stream.str(), '\n'),
"grpc.reflection.v1alpha.ServerReflection\n")); ::testing::UnorderedElementsAre(
"grpc.testing.EchoTestService", "grpc.reflection.v1.ServerReflection",
"grpc.reflection.v1alpha.ServerReflection", ""));
absl::SetFlag(&FLAGS_channel_creds_type, ""); absl::SetFlag(&FLAGS_channel_creds_type, "");
absl::SetFlag(&FLAGS_ssl_target, ""); absl::SetFlag(&FLAGS_ssl_target, "");
@ -1420,9 +1426,11 @@ TEST_F(GrpcToolTest, ConfiguringDefaultServiceConfig) {
std::bind(PrintStream, &output_stream, std::bind(PrintStream, &output_stream,
std::placeholders::_1))); std::placeholders::_1)));
absl::SetFlag(&FLAGS_default_service_config, ""); absl::SetFlag(&FLAGS_default_service_config, "");
EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), EXPECT_THAT(
"grpc.testing.EchoTestService\n" absl::StrSplit(output_stream.str().c_str(), '\n'),
"grpc.reflection.v1alpha.ServerReflection\n")); ::testing::UnorderedElementsAre(
"grpc.testing.EchoTestService", "grpc.reflection.v1.ServerReflection",
"grpc.reflection.v1alpha.ServerReflection", ""));
ShutdownServer(); ShutdownServer();
} }

Loading…
Cancel
Save