reflection: expose both v1 and v1alpha reflection services (#6329)

This commit is contained in:
Joshua Humphries 2023-06-12 17:21:44 -04:00 committed by GitHub
parent 3c6084b7d4
commit 642dd63a85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 411 additions and 100 deletions

187
reflection/adapt.go Normal file
View File

@ -0,0 +1,187 @@
/*
*
* Copyright 2023 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.
*
*/
package reflection
import (
v1grpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1pb "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
)
// asV1Alpha returns an implementation of the v1alpha version of the reflection
// interface that delegates all calls to the given v1 version.
func asV1Alpha(svr v1grpc.ServerReflectionServer) v1alphagrpc.ServerReflectionServer {
return v1AlphaServerImpl{svr: svr}
}
type v1AlphaServerImpl struct {
svr v1grpc.ServerReflectionServer
}
func (s v1AlphaServerImpl) ServerReflectionInfo(stream v1alphagrpc.ServerReflection_ServerReflectionInfoServer) error {
return s.svr.ServerReflectionInfo(v1AlphaServerStreamAdapter{stream})
}
type v1AlphaServerStreamAdapter struct {
v1alphagrpc.ServerReflection_ServerReflectionInfoServer
}
func (s v1AlphaServerStreamAdapter) Send(response *v1pb.ServerReflectionResponse) error {
return s.ServerReflection_ServerReflectionInfoServer.Send(v1ToV1AlphaResponse(response))
}
func (s v1AlphaServerStreamAdapter) Recv() (*v1pb.ServerReflectionRequest, error) {
resp, err := s.ServerReflection_ServerReflectionInfoServer.Recv()
if err != nil {
return nil, err
}
return v1AlphaToV1Request(resp), nil
}
func v1ToV1AlphaResponse(v1 *v1pb.ServerReflectionResponse) *v1alphapb.ServerReflectionResponse {
var v1alpha v1alphapb.ServerReflectionResponse
v1alpha.ValidHost = v1.ValidHost
if v1.OriginalRequest != nil {
v1alpha.OriginalRequest = v1ToV1AlphaRequest(v1.OriginalRequest)
}
switch mr := v1.MessageResponse.(type) {
case *v1pb.ServerReflectionResponse_FileDescriptorResponse:
if mr != nil {
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{
FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(),
},
}
}
case *v1pb.ServerReflectionResponse_AllExtensionNumbersResponse:
if mr != nil {
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse{
AllExtensionNumbersResponse: &v1alphapb.ExtensionNumberResponse{
BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(),
ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(),
},
}
}
case *v1pb.ServerReflectionResponse_ListServicesResponse:
if mr != nil {
svcs := make([]*v1alphapb.ServiceResponse, len(mr.ListServicesResponse.GetService()))
for i, svc := range mr.ListServicesResponse.GetService() {
svcs[i] = &v1alphapb.ServiceResponse{
Name: svc.GetName(),
}
}
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &v1alphapb.ListServiceResponse{
Service: svcs,
},
}
}
case *v1pb.ServerReflectionResponse_ErrorResponse:
if mr != nil {
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{
ErrorCode: mr.ErrorResponse.GetErrorCode(),
ErrorMessage: mr.ErrorResponse.GetErrorMessage(),
},
}
}
default:
// no value set
}
return &v1alpha
}
func v1AlphaToV1Request(v1alpha *v1alphapb.ServerReflectionRequest) *v1pb.ServerReflectionRequest {
var v1 v1pb.ServerReflectionRequest
v1.Host = v1alpha.Host
switch mr := v1alpha.MessageRequest.(type) {
case *v1alphapb.ServerReflectionRequest_FileByFilename:
v1.MessageRequest = &v1pb.ServerReflectionRequest_FileByFilename{
FileByFilename: mr.FileByFilename,
}
case *v1alphapb.ServerReflectionRequest_FileContainingSymbol:
v1.MessageRequest = &v1pb.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: mr.FileContainingSymbol,
}
case *v1alphapb.ServerReflectionRequest_FileContainingExtension:
if mr.FileContainingExtension != nil {
v1.MessageRequest = &v1pb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &v1pb.ExtensionRequest{
ContainingType: mr.FileContainingExtension.GetContainingType(),
ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(),
},
}
}
case *v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType:
v1.MessageRequest = &v1pb.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType,
}
case *v1alphapb.ServerReflectionRequest_ListServices:
v1.MessageRequest = &v1pb.ServerReflectionRequest_ListServices{
ListServices: mr.ListServices,
}
default:
// no value set
}
return &v1
}
func v1ToV1AlphaRequest(v1 *v1pb.ServerReflectionRequest) *v1alphapb.ServerReflectionRequest {
var v1alpha v1alphapb.ServerReflectionRequest
v1alpha.Host = v1.Host
switch mr := v1.MessageRequest.(type) {
case *v1pb.ServerReflectionRequest_FileByFilename:
if mr != nil {
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_FileByFilename{
FileByFilename: mr.FileByFilename,
}
}
case *v1pb.ServerReflectionRequest_FileContainingSymbol:
if mr != nil {
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: mr.FileContainingSymbol,
}
}
case *v1pb.ServerReflectionRequest_FileContainingExtension:
if mr != nil {
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &v1alphapb.ExtensionRequest{
ContainingType: mr.FileContainingExtension.GetContainingType(),
ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(),
},
}
}
case *v1pb.ServerReflectionRequest_AllExtensionNumbersOfType:
if mr != nil {
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType,
}
}
case *v1pb.ServerReflectionRequest_ListServices:
if mr != nil {
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_ListServices{
ListServices: mr.ListServices,
}
}
default:
// no value set
}
return &v1alpha
}

View File

@ -48,8 +48,9 @@ import (
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
v1grpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1pb "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
) )
// GRPCServer is the interface provided by a gRPC server. It is implemented by // GRPCServer is the interface provided by a gRPC server. It is implemented by
@ -63,9 +64,19 @@ type GRPCServer interface {
var _ GRPCServer = (*grpc.Server)(nil) var _ GRPCServer = (*grpc.Server)(nil)
// Register registers the server reflection service on the given gRPC server. // Register registers the server reflection service on the given gRPC server.
// Both the v1 and v1alpha versions are registered.
func Register(s GRPCServer) { func Register(s GRPCServer) {
svr := NewServer(ServerOptions{Services: s}) svr := NewServerV1(ServerOptions{Services: s})
v1alphagrpc.RegisterServerReflectionServer(s, svr) v1alphagrpc.RegisterServerReflectionServer(s, asV1Alpha(svr))
v1grpc.RegisterServerReflectionServer(s, svr)
}
// RegisterV1 registers only the v1 version of the server reflection service
// on the given gRPC server. Many clients may only support v1alpha so most
// users should use Register instead, at least until clients have upgraded.
func RegisterV1(s GRPCServer) {
svr := NewServerV1(ServerOptions{Services: s})
v1grpc.RegisterServerReflectionServer(s, svr)
} }
// ServiceInfoProvider is an interface used to retrieve metadata about the // ServiceInfoProvider is an interface used to retrieve metadata about the
@ -120,13 +131,27 @@ type ServerOptions struct {
// NewServer returns a reflection server implementation using the given options. // NewServer returns a reflection server implementation using the given options.
// This can be used to customize behavior of the reflection service. Most usages // This can be used to customize behavior of the reflection service. Most usages
// should prefer to use Register instead. // should prefer to use Register instead. For backwards compatibility reasons,
// this returns the v1alpha version of the reflection server. For a v1 version
// of the reflection server, see NewServerV1.
// //
// # Experimental // # Experimental
// //
// Notice: This function is EXPERIMENTAL and may be changed or removed in a // Notice: This function is EXPERIMENTAL and may be changed or removed in a
// later release. // later release.
func NewServer(opts ServerOptions) v1alphagrpc.ServerReflectionServer { func NewServer(opts ServerOptions) v1alphagrpc.ServerReflectionServer {
return asV1Alpha(NewServerV1(opts))
}
// NewServerV1 returns a reflection server implementation using the given options.
// This can be used to customize behavior of the reflection service. Most usages
// should prefer to use Register instead.
//
// # Experimental
//
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
// later release.
func NewServerV1(opts ServerOptions) v1grpc.ServerReflectionServer {
if opts.DescriptorResolver == nil { if opts.DescriptorResolver == nil {
opts.DescriptorResolver = protoregistry.GlobalFiles opts.DescriptorResolver = protoregistry.GlobalFiles
} }
@ -215,11 +240,11 @@ func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]
} }
// listServices returns the names of services this server exposes. // listServices returns the names of services this server exposes.
func (s *serverReflectionServer) listServices() []*v1alphapb.ServiceResponse { func (s *serverReflectionServer) listServices() []*v1pb.ServiceResponse {
serviceInfo := s.s.GetServiceInfo() serviceInfo := s.s.GetServiceInfo()
resp := make([]*v1alphapb.ServiceResponse, 0, len(serviceInfo)) resp := make([]*v1pb.ServiceResponse, 0, len(serviceInfo))
for svc := range serviceInfo { for svc := range serviceInfo {
resp = append(resp, &v1alphapb.ServiceResponse{Name: svc}) resp = append(resp, &v1pb.ServiceResponse{Name: svc})
} }
sort.Slice(resp, func(i, j int) bool { sort.Slice(resp, func(i, j int) bool {
return resp[i].Name < resp[j].Name return resp[i].Name < resp[j].Name
@ -228,7 +253,7 @@ func (s *serverReflectionServer) listServices() []*v1alphapb.ServiceResponse {
} }
// ServerReflectionInfo is the reflection service handler. // ServerReflectionInfo is the reflection service handler.
func (s *serverReflectionServer) ServerReflectionInfo(stream v1alphagrpc.ServerReflection_ServerReflectionInfoServer) error { func (s *serverReflectionServer) ServerReflectionInfo(stream v1grpc.ServerReflection_ServerReflectionInfoServer) error {
sentFileDescriptors := make(map[string]bool) sentFileDescriptors := make(map[string]bool)
for { for {
in, err := stream.Recv() in, err := stream.Recv()
@ -239,79 +264,79 @@ func (s *serverReflectionServer) ServerReflectionInfo(stream v1alphagrpc.ServerR
return err return err
} }
out := &v1alphapb.ServerReflectionResponse{ out := &v1pb.ServerReflectionResponse{
ValidHost: in.Host, ValidHost: in.Host,
OriginalRequest: in, OriginalRequest: in,
} }
switch req := in.MessageRequest.(type) { switch req := in.MessageRequest.(type) {
case *v1alphapb.ServerReflectionRequest_FileByFilename: case *v1pb.ServerReflectionRequest_FileByFilename:
var b [][]byte var b [][]byte
fd, err := s.descResolver.FindFileByPath(req.FileByFilename) fd, err := s.descResolver.FindFileByPath(req.FileByFilename)
if err == nil { if err == nil {
b, err = s.fileDescWithDependencies(fd, sentFileDescriptors) b, err = s.fileDescWithDependencies(fd, sentFileDescriptors)
} }
if err != nil { if err != nil {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{ ErrorResponse: &v1pb.ErrorResponse{
ErrorCode: int32(codes.NotFound), ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(), ErrorMessage: err.Error(),
}, },
} }
} else { } else {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b}, FileDescriptorResponse: &v1pb.FileDescriptorResponse{FileDescriptorProto: b},
} }
} }
case *v1alphapb.ServerReflectionRequest_FileContainingSymbol: case *v1pb.ServerReflectionRequest_FileContainingSymbol:
b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors) b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
if err != nil { if err != nil {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{ ErrorResponse: &v1pb.ErrorResponse{
ErrorCode: int32(codes.NotFound), ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(), ErrorMessage: err.Error(),
}, },
} }
} else { } else {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b}, FileDescriptorResponse: &v1pb.FileDescriptorResponse{FileDescriptorProto: b},
} }
} }
case *v1alphapb.ServerReflectionRequest_FileContainingExtension: case *v1pb.ServerReflectionRequest_FileContainingExtension:
typeName := req.FileContainingExtension.ContainingType typeName := req.FileContainingExtension.ContainingType
extNum := req.FileContainingExtension.ExtensionNumber extNum := req.FileContainingExtension.ExtensionNumber
b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors) b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
if err != nil { if err != nil {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{ ErrorResponse: &v1pb.ErrorResponse{
ErrorCode: int32(codes.NotFound), ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(), ErrorMessage: err.Error(),
}, },
} }
} else { } else {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b}, FileDescriptorResponse: &v1pb.FileDescriptorResponse{FileDescriptorProto: b},
} }
} }
case *v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType: case *v1pb.ServerReflectionRequest_AllExtensionNumbersOfType:
extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType) extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType)
if err != nil { if err != nil {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{ ErrorResponse: &v1pb.ErrorResponse{
ErrorCode: int32(codes.NotFound), ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(), ErrorMessage: err.Error(),
}, },
} }
} else { } else {
out.MessageResponse = &v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_AllExtensionNumbersResponse{
AllExtensionNumbersResponse: &v1alphapb.ExtensionNumberResponse{ AllExtensionNumbersResponse: &v1pb.ExtensionNumberResponse{
BaseTypeName: req.AllExtensionNumbersOfType, BaseTypeName: req.AllExtensionNumbersOfType,
ExtensionNumber: extNums, ExtensionNumber: extNums,
}, },
} }
} }
case *v1alphapb.ServerReflectionRequest_ListServices: case *v1pb.ServerReflectionRequest_ListServices:
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ListServicesResponse{ out.MessageResponse = &v1pb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &v1alphapb.ListServiceResponse{ ListServicesResponse: &v1pb.ListServiceResponse{
Service: s.listServices(), Service: s.listServices(),
}, },
} }

View File

@ -37,6 +37,8 @@ import (
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/dynamicpb" "google.golang.org/protobuf/types/dynamicpb"
v1grpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1pb "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
pb "google.golang.org/grpc/reflection/grpc_testing" pb "google.golang.org/grpc/reflection/grpc_testing"
@ -44,11 +46,8 @@ import (
) )
var ( var (
s = NewServer(ServerOptions{}).(*serverReflectionServer) s = NewServerV1(ServerOptions{}).(*serverReflectionServer)
// fileDescriptor of each test proto file. // fileDescriptor of each test proto file.
fdTest *descriptorpb.FileDescriptorProto
fdTestv3 *descriptorpb.FileDescriptorProto
fdProto2 *descriptorpb.FileDescriptorProto
fdProto2Ext *descriptorpb.FileDescriptorProto fdProto2Ext *descriptorpb.FileDescriptorProto
fdProto2Ext2 *descriptorpb.FileDescriptorProto fdProto2Ext2 *descriptorpb.FileDescriptorProto
fdDynamic *descriptorpb.FileDescriptorProto fdDynamic *descriptorpb.FileDescriptorProto
@ -113,9 +112,9 @@ func loadFileDescDynamic(b []byte) (*descriptorpb.FileDescriptorProto, protorefl
} }
func init() { func init() {
fdTest, fdTestByte = loadFileDesc("reflection/grpc_testing/test.proto") _, fdTestByte = loadFileDesc("reflection/grpc_testing/test.proto")
fdTestv3, fdTestv3Byte = loadFileDesc("testv3.proto") _, fdTestv3Byte = loadFileDesc("testv3.proto")
fdProto2, fdProto2Byte = loadFileDesc("reflection/grpc_testing/proto2.proto") _, fdProto2Byte = loadFileDesc("reflection/grpc_testing/proto2.proto")
fdProto2Ext, fdProto2ExtByte = loadFileDesc("reflection/grpc_testing/proto2_ext.proto") fdProto2Ext, fdProto2ExtByte = loadFileDesc("reflection/grpc_testing/proto2_ext.proto")
fdProto2Ext2, fdProto2Ext2Byte = loadFileDesc("reflection/grpc_testing/proto2_ext2.proto") fdProto2Ext2, fdProto2Ext2Byte = loadFileDesc("reflection/grpc_testing/proto2_ext2.proto")
fdDynamic, fdDynamicFile, fdDynamicByte = loadFileDescDynamic(pbv3.FileDynamicProtoRawDesc) fdDynamic, fdDynamicFile, fdDynamicByte = loadFileDescDynamic(pbv3.FileDynamicProtoRawDesc)
@ -210,6 +209,7 @@ func (x) TestReflectionEnd2end(t *testing.T) {
// Register reflection service on s. // Register reflection service on s.
Register(s) Register(s)
go s.Serve(lis) go s.Serve(lis)
t.Cleanup(s.Stop)
// Create client. // Create client.
conn, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) conn, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
@ -218,33 +218,50 @@ func (x) TestReflectionEnd2end(t *testing.T) {
} }
defer conn.Close() defer conn.Close()
c := v1alphagrpc.NewServerReflectionClient(conn) clientV1 := v1grpc.NewServerReflectionClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) clientV1Alpha := v1alphagrpc.NewServerReflectionClient(conn)
defer cancel() testCases := []struct {
stream, err := c.ServerReflectionInfo(ctx, grpc.WaitForReady(true)) name string
if err != nil { client v1grpc.ServerReflectionClient
t.Fatalf("cannot get ServerReflectionInfo: %v", err) }{
{
name: "v1",
client: clientV1,
},
{
name: "v1alpha",
client: v1AlphaClientAdapter{stub: clientV1Alpha},
},
} }
for _, testCase := range testCases {
c := testCase.client
t.Run(testCase.name, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
defer cancel()
stream, err := c.ServerReflectionInfo(ctx, grpc.WaitForReady(true))
if err != nil {
t.Fatalf("cannot get ServerReflectionInfo: %v", err)
}
testFileByFilenameTransitiveClosure(t, stream, true) testFileByFilenameTransitiveClosure(t, stream, true)
testFileByFilenameTransitiveClosure(t, stream, false) testFileByFilenameTransitiveClosure(t, stream, false)
testFileByFilename(t, stream) testFileByFilename(t, stream)
testFileByFilenameError(t, stream) testFileByFilenameError(t, stream)
testFileContainingSymbol(t, stream) testFileContainingSymbol(t, stream)
testFileContainingSymbolError(t, stream) testFileContainingSymbolError(t, stream)
testFileContainingExtension(t, stream) testFileContainingExtension(t, stream)
testFileContainingExtensionError(t, stream) testFileContainingExtensionError(t, stream)
testAllExtensionNumbersOfType(t, stream) testAllExtensionNumbersOfType(t, stream)
testAllExtensionNumbersOfTypeError(t, stream) testAllExtensionNumbersOfTypeError(t, stream)
testListServices(t, stream) testListServices(t, stream)
})
s.Stop() }
} }
func testFileByFilenameTransitiveClosure(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient, expectClosure bool) { func testFileByFilenameTransitiveClosure(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient, expectClosure bool) {
filename := "reflection/grpc_testing/proto2_ext2.proto" filename := "reflection/grpc_testing/proto2_ext2.proto"
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileByFilename{ MessageRequest: &v1pb.ServerReflectionRequest_FileByFilename{
FileByFilename: filename, FileByFilename: filename,
}, },
}); err != nil { }); err != nil {
@ -256,7 +273,7 @@ func testFileByFilenameTransitiveClosure(t *testing.T, stream v1alphagrpc.Server
t.Fatalf("failed to recv response: %v", err) t.Fatalf("failed to recv response: %v", err)
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse: case *v1pb.ServerReflectionResponse_FileDescriptorResponse:
if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) { if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) {
t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte)
} }
@ -274,7 +291,7 @@ func testFileByFilenameTransitiveClosure(t *testing.T, stream v1alphagrpc.Server
} }
} }
func testFileByFilename(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testFileByFilename(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct { for _, test := range []struct {
filename string filename string
want []byte want []byte
@ -284,8 +301,8 @@ func testFileByFilename(t *testing.T, stream v1alphagrpc.ServerReflection_Server
{"reflection/grpc_testing/proto2_ext.proto", fdProto2ExtByte}, {"reflection/grpc_testing/proto2_ext.proto", fdProto2ExtByte},
{"dynamic.proto", fdDynamicByte}, {"dynamic.proto", fdDynamicByte},
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileByFilename{ MessageRequest: &v1pb.ServerReflectionRequest_FileByFilename{
FileByFilename: test.filename, FileByFilename: test.filename,
}, },
}); err != nil { }); err != nil {
@ -298,7 +315,7 @@ func testFileByFilename(t *testing.T, stream v1alphagrpc.ServerReflection_Server
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse: case *v1pb.ServerReflectionResponse_FileDescriptorResponse:
if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) {
t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", test.filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", test.filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want)
} }
@ -308,14 +325,14 @@ func testFileByFilename(t *testing.T, stream v1alphagrpc.ServerReflection_Server
} }
} }
func testFileByFilenameError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testFileByFilenameError(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []string{ for _, test := range []string{
"test.poto", "test.poto",
"proo2.proto", "proo2.proto",
"proto2_et.proto", "proto2_et.proto",
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileByFilename{ MessageRequest: &v1pb.ServerReflectionRequest_FileByFilename{
FileByFilename: test, FileByFilename: test,
}, },
}); err != nil { }); err != nil {
@ -328,14 +345,14 @@ func testFileByFilenameError(t *testing.T, stream v1alphagrpc.ServerReflection_S
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_ErrorResponse: case *v1pb.ServerReflectionResponse_ErrorResponse:
default: default:
t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse) t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
} }
} }
} }
func testFileContainingSymbol(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testFileContainingSymbol(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct { for _, test := range []struct {
symbol string symbol string
want []byte want []byte
@ -361,8 +378,8 @@ func testFileContainingSymbol(t *testing.T, stream v1alphagrpc.ServerReflection_
{"grpc.testing.DynamicReq", fdDynamicByte}, {"grpc.testing.DynamicReq", fdDynamicByte},
{"grpc.testing.DynamicRes", fdDynamicByte}, {"grpc.testing.DynamicRes", fdDynamicByte},
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingSymbol{ MessageRequest: &v1pb.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: test.symbol, FileContainingSymbol: test.symbol,
}, },
}); err != nil { }); err != nil {
@ -375,7 +392,7 @@ func testFileContainingSymbol(t *testing.T, stream v1alphagrpc.ServerReflection_
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse: case *v1pb.ServerReflectionResponse_FileDescriptorResponse:
if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) {
t.Errorf("FileContainingSymbol(%v)\nreceived: %q,\nwant: %q", test.symbol, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) t.Errorf("FileContainingSymbol(%v)\nreceived: %q,\nwant: %q", test.symbol, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want)
} }
@ -385,15 +402,15 @@ func testFileContainingSymbol(t *testing.T, stream v1alphagrpc.ServerReflection_
} }
} }
func testFileContainingSymbolError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testFileContainingSymbolError(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []string{ for _, test := range []string{
"grpc.testing.SerchService", "grpc.testing.SerchService",
"grpc.testing.SearchService.SearchE", "grpc.testing.SearchService.SearchE",
"grpc.tesing.SearchResponse", "grpc.tesing.SearchResponse",
"gpc.testing.ToBeExtended", "gpc.testing.ToBeExtended",
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingSymbol{ MessageRequest: &v1pb.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: test, FileContainingSymbol: test,
}, },
}); err != nil { }); err != nil {
@ -406,14 +423,14 @@ func testFileContainingSymbolError(t *testing.T, stream v1alphagrpc.ServerReflec
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_ErrorResponse: case *v1pb.ServerReflectionResponse_ErrorResponse:
default: default:
t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse) t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
} }
} }
} }
func testFileContainingExtension(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testFileContainingExtension(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct { for _, test := range []struct {
typeName string typeName string
extNum int32 extNum int32
@ -425,9 +442,9 @@ func testFileContainingExtension(t *testing.T, stream v1alphagrpc.ServerReflecti
{"grpc.testing.ToBeExtended", 23, fdProto2Ext2Byte}, {"grpc.testing.ToBeExtended", 23, fdProto2Ext2Byte},
{"grpc.testing.ToBeExtended", 29, fdProto2Ext2Byte}, {"grpc.testing.ToBeExtended", 29, fdProto2Ext2Byte},
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingExtension{ MessageRequest: &v1pb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &v1alphapb.ExtensionRequest{ FileContainingExtension: &v1pb.ExtensionRequest{
ContainingType: test.typeName, ContainingType: test.typeName,
ExtensionNumber: test.extNum, ExtensionNumber: test.extNum,
}, },
@ -442,7 +459,7 @@ func testFileContainingExtension(t *testing.T, stream v1alphagrpc.ServerReflecti
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse: case *v1pb.ServerReflectionResponse_FileDescriptorResponse:
if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) {
t.Errorf("FileContainingExtension(%v, %v)\nreceived: %q,\nwant: %q", test.typeName, test.extNum, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) t.Errorf("FileContainingExtension(%v, %v)\nreceived: %q,\nwant: %q", test.typeName, test.extNum, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want)
} }
@ -452,7 +469,7 @@ func testFileContainingExtension(t *testing.T, stream v1alphagrpc.ServerReflecti
} }
} }
func testFileContainingExtensionError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testFileContainingExtensionError(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct { for _, test := range []struct {
typeName string typeName string
extNum int32 extNum int32
@ -460,9 +477,9 @@ func testFileContainingExtensionError(t *testing.T, stream v1alphagrpc.ServerRef
{"grpc.testing.ToBExtended", 17}, {"grpc.testing.ToBExtended", 17},
{"grpc.testing.ToBeExtended", 15}, {"grpc.testing.ToBeExtended", 15},
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingExtension{ MessageRequest: &v1pb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &v1alphapb.ExtensionRequest{ FileContainingExtension: &v1pb.ExtensionRequest{
ContainingType: test.typeName, ContainingType: test.typeName,
ExtensionNumber: test.extNum, ExtensionNumber: test.extNum,
}, },
@ -477,14 +494,14 @@ func testFileContainingExtensionError(t *testing.T, stream v1alphagrpc.ServerRef
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_ErrorResponse: case *v1pb.ServerReflectionResponse_ErrorResponse:
default: default:
t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse) t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse)
} }
} }
} }
func testAllExtensionNumbersOfType(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testAllExtensionNumbersOfType(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct { for _, test := range []struct {
typeName string typeName string
want []int32 want []int32
@ -492,8 +509,8 @@ func testAllExtensionNumbersOfType(t *testing.T, stream v1alphagrpc.ServerReflec
{"grpc.testing.ToBeExtended", []int32{13, 17, 19, 23, 29}}, {"grpc.testing.ToBeExtended", []int32{13, 17, 19, 23, 29}},
{"grpc.testing.DynamicReq", nil}, {"grpc.testing.DynamicReq", nil},
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType{ MessageRequest: &v1pb.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: test.typeName, AllExtensionNumbersOfType: test.typeName,
}, },
}); err != nil { }); err != nil {
@ -506,7 +523,7 @@ func testAllExtensionNumbersOfType(t *testing.T, stream v1alphagrpc.ServerReflec
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse: case *v1pb.ServerReflectionResponse_AllExtensionNumbersResponse:
extNum := r.GetAllExtensionNumbersResponse().ExtensionNumber extNum := r.GetAllExtensionNumbersResponse().ExtensionNumber
sort.Sort(intArray(extNum)) sort.Sort(intArray(extNum))
if r.GetAllExtensionNumbersResponse().BaseTypeName != test.typeName || if r.GetAllExtensionNumbersResponse().BaseTypeName != test.typeName ||
@ -519,12 +536,12 @@ func testAllExtensionNumbersOfType(t *testing.T, stream v1alphagrpc.ServerReflec
} }
} }
func testAllExtensionNumbersOfTypeError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testAllExtensionNumbersOfTypeError(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []string{ for _, test := range []string{
"grpc.testing.ToBeExtendedE", "grpc.testing.ToBeExtendedE",
} { } {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType{ MessageRequest: &v1pb.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: test, AllExtensionNumbersOfType: test,
}, },
}); err != nil { }); err != nil {
@ -537,16 +554,16 @@ func testAllExtensionNumbersOfTypeError(t *testing.T, stream v1alphagrpc.ServerR
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_ErrorResponse: case *v1pb.ServerReflectionResponse_ErrorResponse:
default: default:
t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse) t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
} }
} }
} }
func testListServices(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) { func testListServices(t *testing.T, stream v1grpc.ServerReflection_ServerReflectionInfoClient) {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{ if err := stream.Send(&v1pb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_ListServices{}, MessageRequest: &v1pb.ServerReflectionRequest_ListServices{},
}); err != nil { }); err != nil {
t.Fatalf("failed to send request: %v", err) t.Fatalf("failed to send request: %v", err)
} }
@ -557,11 +574,12 @@ func testListServices(t *testing.T, stream v1alphagrpc.ServerReflection_ServerRe
} }
switch r.MessageResponse.(type) { switch r.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_ListServicesResponse: case *v1pb.ServerReflectionResponse_ListServicesResponse:
services := r.GetListServicesResponse().Service services := r.GetListServicesResponse().Service
want := []string{ want := []string{
"grpc.testingv3.SearchServiceV3", "grpc.testingv3.SearchServiceV3",
"grpc.testing.SearchService", "grpc.testing.SearchService",
"grpc.reflection.v1.ServerReflection",
"grpc.reflection.v1alpha.ServerReflection", "grpc.reflection.v1alpha.ServerReflection",
"grpc.testing.DynamicService", "grpc.testing.DynamicService",
} }
@ -607,3 +625,84 @@ func registerDynamicProto(srv *grpc.Server, fdp *descriptorpb.FileDescriptorProt
srv.RegisterService(sd, struct{}{}) srv.RegisterService(sd, struct{}{})
} }
} }
type v1AlphaClientAdapter struct {
stub v1alphagrpc.ServerReflectionClient
}
func (v v1AlphaClientAdapter) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (v1grpc.ServerReflection_ServerReflectionInfoClient, error) {
stream, err := v.stub.ServerReflectionInfo(ctx, opts...)
if err != nil {
return nil, err
}
return v1AlphaClientStreamAdapter{stream}, nil
}
type v1AlphaClientStreamAdapter struct {
v1alphagrpc.ServerReflection_ServerReflectionInfoClient
}
func (s v1AlphaClientStreamAdapter) Send(request *v1pb.ServerReflectionRequest) error {
return s.ServerReflection_ServerReflectionInfoClient.Send(v1ToV1AlphaRequest(request))
}
func (s v1AlphaClientStreamAdapter) Recv() (*v1pb.ServerReflectionResponse, error) {
resp, err := s.ServerReflection_ServerReflectionInfoClient.Recv()
if err != nil {
return nil, err
}
return v1AlphaToV1Response(resp), nil
}
func v1AlphaToV1Response(v1alpha *v1alphapb.ServerReflectionResponse) *v1pb.ServerReflectionResponse {
var v1 v1pb.ServerReflectionResponse
v1.ValidHost = v1alpha.ValidHost
if v1alpha.OriginalRequest != nil {
v1.OriginalRequest = v1AlphaToV1Request(v1alpha.OriginalRequest)
}
switch mr := v1alpha.MessageResponse.(type) {
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse:
if mr != nil {
v1.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1pb.FileDescriptorResponse{
FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(),
},
}
}
case *v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse:
if mr != nil {
v1.MessageResponse = &v1pb.ServerReflectionResponse_AllExtensionNumbersResponse{
AllExtensionNumbersResponse: &v1pb.ExtensionNumberResponse{
BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(),
ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(),
},
}
}
case *v1alphapb.ServerReflectionResponse_ListServicesResponse:
if mr != nil {
svcs := make([]*v1pb.ServiceResponse, len(mr.ListServicesResponse.GetService()))
for i, svc := range mr.ListServicesResponse.GetService() {
svcs[i] = &v1pb.ServiceResponse{
Name: svc.GetName(),
}
}
v1.MessageResponse = &v1pb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &v1pb.ListServiceResponse{
Service: svcs,
},
}
}
case *v1alphapb.ServerReflectionResponse_ErrorResponse:
if mr != nil {
v1.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1pb.ErrorResponse{
ErrorCode: mr.ErrorResponse.GetErrorCode(),
ErrorMessage: mr.ErrorResponse.GetErrorMessage(),
},
}
}
default:
// no value set
}
return &v1
}