reflection: split grpc and pb imports (#5810)

This commit is contained in:
Easwar Swaminathan
2022-11-22 10:40:31 -08:00
committed by GitHub
parent 6f96f961f3
commit e0a9f1112a
2 changed files with 82 additions and 78 deletions

View File

@ -42,12 +42,14 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
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
@ -63,7 +65,7 @@ var _ GRPCServer = (*grpc.Server)(nil)
// Register registers the server reflection service on the given gRPC server.
func Register(s GRPCServer) {
svr := NewServer(ServerOptions{Services: s})
rpb.RegisterServerReflectionServer(s, svr)
v1alphagrpc.RegisterServerReflectionServer(s, svr)
}
// ServiceInfoProvider is an interface used to retrieve metadata about the
@ -124,7 +126,7 @@ type ServerOptions struct {
//
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
// later release.
func NewServer(opts ServerOptions) rpb.ServerReflectionServer {
func NewServer(opts ServerOptions) v1alphagrpc.ServerReflectionServer {
if opts.DescriptorResolver == nil {
opts.DescriptorResolver = protoregistry.GlobalFiles
}
@ -139,7 +141,7 @@ func NewServer(opts ServerOptions) rpb.ServerReflectionServer {
}
type serverReflectionServer struct {
rpb.UnimplementedServerReflectionServer
v1alphagrpc.UnimplementedServerReflectionServer
s ServiceInfoProvider
descResolver protodesc.Resolver
extResolver ExtensionResolver
@ -213,11 +215,11 @@ func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]
}
// listServices returns the names of services this server exposes.
func (s *serverReflectionServer) listServices() []*rpb.ServiceResponse {
func (s *serverReflectionServer) listServices() []*v1alphapb.ServiceResponse {
serviceInfo := s.s.GetServiceInfo()
resp := make([]*rpb.ServiceResponse, 0, len(serviceInfo))
resp := make([]*v1alphapb.ServiceResponse, 0, len(serviceInfo))
for svc := range serviceInfo {
resp = append(resp, &rpb.ServiceResponse{Name: svc})
resp = append(resp, &v1alphapb.ServiceResponse{Name: svc})
}
sort.Slice(resp, func(i, j int) bool {
return resp[i].Name < resp[j].Name
@ -226,7 +228,7 @@ func (s *serverReflectionServer) listServices() []*rpb.ServiceResponse {
}
// ServerReflectionInfo is the reflection service handler.
func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflection_ServerReflectionInfoServer) error {
func (s *serverReflectionServer) ServerReflectionInfo(stream v1alphagrpc.ServerReflection_ServerReflectionInfoServer) error {
sentFileDescriptors := make(map[string]bool)
for {
in, err := stream.Recv()
@ -237,79 +239,79 @@ func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflectio
return err
}
out := &rpb.ServerReflectionResponse{
out := &v1alphapb.ServerReflectionResponse{
ValidHost: in.Host,
OriginalRequest: in,
}
switch req := in.MessageRequest.(type) {
case *rpb.ServerReflectionRequest_FileByFilename:
case *v1alphapb.ServerReflectionRequest_FileByFilename:
var b [][]byte
fd, err := s.descResolver.FindFileByPath(req.FileByFilename)
if err == nil {
b, err = s.fileDescWithDependencies(fd, sentFileDescriptors)
}
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: b},
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
}
}
case *rpb.ServerReflectionRequest_FileContainingSymbol:
case *v1alphapb.ServerReflectionRequest_FileContainingSymbol:
b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: b},
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
}
}
case *rpb.ServerReflectionRequest_FileContainingExtension:
case *v1alphapb.ServerReflectionRequest_FileContainingExtension:
typeName := req.FileContainingExtension.ContainingType
extNum := req.FileContainingExtension.ExtensionNumber
b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &rpb.FileDescriptorResponse{FileDescriptorProto: b},
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
}
}
case *rpb.ServerReflectionRequest_AllExtensionNumbersOfType:
case *v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType:
extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType)
if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &v1alphapb.ErrorResponse{
ErrorCode: int32(codes.NotFound),
ErrorMessage: err.Error(),
},
}
} else {
out.MessageResponse = &rpb.ServerReflectionResponse_AllExtensionNumbersResponse{
AllExtensionNumbersResponse: &rpb.ExtensionNumberResponse{
out.MessageResponse = &v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse{
AllExtensionNumbersResponse: &v1alphapb.ExtensionNumberResponse{
BaseTypeName: req.AllExtensionNumbersOfType,
ExtensionNumber: extNums,
},
}
}
case *rpb.ServerReflectionRequest_ListServices:
out.MessageResponse = &rpb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &rpb.ListServiceResponse{
case *v1alphapb.ServerReflectionRequest_ListServices:
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &v1alphapb.ListServiceResponse{
Service: s.listServices(),
},
}

View File

@ -30,15 +30,17 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/internal/grpctest"
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
pb "google.golang.org/grpc/reflection/grpc_testing"
pbv3 "google.golang.org/grpc/reflection/grpc_testing_not_regenerate"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/dynamicpb"
v1alphagrpc "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"
pbv3 "google.golang.org/grpc/reflection/grpc_testing_not_regenerate"
)
var (
@ -216,7 +218,7 @@ func (x) TestReflectionEnd2end(t *testing.T) {
}
defer conn.Close()
c := rpb.NewServerReflectionClient(conn)
c := v1alphagrpc.NewServerReflectionClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
defer cancel()
stream, err := c.ServerReflectionInfo(ctx, grpc.WaitForReady(true))
@ -239,10 +241,10 @@ func (x) TestReflectionEnd2end(t *testing.T) {
s.Stop()
}
func testFileByFilenameTransitiveClosure(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient, expectClosure bool) {
func testFileByFilenameTransitiveClosure(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient, expectClosure bool) {
filename := "reflection/grpc_testing/proto2_ext2.proto"
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileByFilename{
FileByFilename: filename,
},
}); err != nil {
@ -254,7 +256,7 @@ func testFileByFilenameTransitiveClosure(t *testing.T, stream rpb.ServerReflecti
t.Fatalf("failed to recv response: %v", err)
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_FileDescriptorResponse:
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse:
if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) {
t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte)
}
@ -272,7 +274,7 @@ func testFileByFilenameTransitiveClosure(t *testing.T, stream rpb.ServerReflecti
}
}
func testFileByFilename(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testFileByFilename(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct {
filename string
want []byte
@ -282,8 +284,8 @@ func testFileByFilename(t *testing.T, stream rpb.ServerReflection_ServerReflecti
{"reflection/grpc_testing/proto2_ext.proto", fdProto2ExtByte},
{"dynamic.proto", fdDynamicByte},
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileByFilename{
FileByFilename: test.filename,
},
}); err != nil {
@ -296,7 +298,7 @@ func testFileByFilename(t *testing.T, stream rpb.ServerReflection_ServerReflecti
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_FileDescriptorResponse:
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse:
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)
}
@ -306,14 +308,14 @@ func testFileByFilename(t *testing.T, stream rpb.ServerReflection_ServerReflecti
}
}
func testFileByFilenameError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testFileByFilenameError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []string{
"test.poto",
"proo2.proto",
"proto2_et.proto",
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileByFilename{
FileByFilename: test,
},
}); err != nil {
@ -326,14 +328,14 @@ func testFileByFilenameError(t *testing.T, stream rpb.ServerReflection_ServerRef
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_ErrorResponse:
case *v1alphapb.ServerReflectionResponse_ErrorResponse:
default:
t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
}
}
}
func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testFileContainingSymbol(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct {
symbol string
want []byte
@ -359,8 +361,8 @@ func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerRe
{"grpc.testing.DynamicReq", fdDynamicByte},
{"grpc.testing.DynamicRes", fdDynamicByte},
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: test.symbol,
},
}); err != nil {
@ -373,7 +375,7 @@ func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerRe
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_FileDescriptorResponse:
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse:
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)
}
@ -383,15 +385,15 @@ func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerRe
}
}
func testFileContainingSymbolError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testFileContainingSymbolError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []string{
"grpc.testing.SerchService",
"grpc.testing.SearchService.SearchE",
"grpc.tesing.SearchResponse",
"gpc.testing.ToBeExtended",
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingSymbol{
FileContainingSymbol: test,
},
}); err != nil {
@ -404,14 +406,14 @@ func testFileContainingSymbolError(t *testing.T, stream rpb.ServerReflection_Ser
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_ErrorResponse:
case *v1alphapb.ServerReflectionResponse_ErrorResponse:
default:
t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
}
}
}
func testFileContainingExtension(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testFileContainingExtension(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct {
typeName string
extNum int32
@ -423,9 +425,9 @@ func testFileContainingExtension(t *testing.T, stream rpb.ServerReflection_Serve
{"grpc.testing.ToBeExtended", 23, fdProto2Ext2Byte},
{"grpc.testing.ToBeExtended", 29, fdProto2Ext2Byte},
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &rpb.ExtensionRequest{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &v1alphapb.ExtensionRequest{
ContainingType: test.typeName,
ExtensionNumber: test.extNum,
},
@ -440,7 +442,7 @@ func testFileContainingExtension(t *testing.T, stream rpb.ServerReflection_Serve
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_FileDescriptorResponse:
case *v1alphapb.ServerReflectionResponse_FileDescriptorResponse:
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)
}
@ -450,7 +452,7 @@ func testFileContainingExtension(t *testing.T, stream rpb.ServerReflection_Serve
}
}
func testFileContainingExtensionError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testFileContainingExtensionError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct {
typeName string
extNum int32
@ -458,9 +460,9 @@ func testFileContainingExtensionError(t *testing.T, stream rpb.ServerReflection_
{"grpc.testing.ToBExtended", 17},
{"grpc.testing.ToBeExtended", 15},
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &rpb.ExtensionRequest{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_FileContainingExtension{
FileContainingExtension: &v1alphapb.ExtensionRequest{
ContainingType: test.typeName,
ExtensionNumber: test.extNum,
},
@ -475,14 +477,14 @@ func testFileContainingExtensionError(t *testing.T, stream rpb.ServerReflection_
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_ErrorResponse:
case *v1alphapb.ServerReflectionResponse_ErrorResponse:
default:
t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse)
}
}
}
func testAllExtensionNumbersOfType(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testAllExtensionNumbersOfType(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []struct {
typeName string
want []int32
@ -490,8 +492,8 @@ func testAllExtensionNumbersOfType(t *testing.T, stream rpb.ServerReflection_Ser
{"grpc.testing.ToBeExtended", []int32{13, 17, 19, 23, 29}},
{"grpc.testing.DynamicReq", nil},
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: test.typeName,
},
}); err != nil {
@ -504,7 +506,7 @@ func testAllExtensionNumbersOfType(t *testing.T, stream rpb.ServerReflection_Ser
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_AllExtensionNumbersResponse:
case *v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse:
extNum := r.GetAllExtensionNumbersResponse().ExtensionNumber
sort.Sort(intArray(extNum))
if r.GetAllExtensionNumbersResponse().BaseTypeName != test.typeName ||
@ -517,12 +519,12 @@ func testAllExtensionNumbersOfType(t *testing.T, stream rpb.ServerReflection_Ser
}
}
func testAllExtensionNumbersOfTypeError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
func testAllExtensionNumbersOfTypeError(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
for _, test := range []string{
"grpc.testing.ToBeExtendedE",
} {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType{
AllExtensionNumbersOfType: test,
},
}); err != nil {
@ -535,16 +537,16 @@ func testAllExtensionNumbersOfTypeError(t *testing.T, stream rpb.ServerReflectio
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_ErrorResponse:
case *v1alphapb.ServerReflectionResponse_ErrorResponse:
default:
t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
}
}
}
func testListServices(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) {
if err := stream.Send(&rpb.ServerReflectionRequest{
MessageRequest: &rpb.ServerReflectionRequest_ListServices{},
func testListServices(t *testing.T, stream v1alphagrpc.ServerReflection_ServerReflectionInfoClient) {
if err := stream.Send(&v1alphapb.ServerReflectionRequest{
MessageRequest: &v1alphapb.ServerReflectionRequest_ListServices{},
}); err != nil {
t.Fatalf("failed to send request: %v", err)
}
@ -555,7 +557,7 @@ func testListServices(t *testing.T, stream rpb.ServerReflection_ServerReflection
}
switch r.MessageResponse.(type) {
case *rpb.ServerReflectionResponse_ListServicesResponse:
case *v1alphapb.ServerReflectionResponse_ListServicesResponse:
services := r.GetListServicesResponse().Service
want := []string{
"grpc.testingv3.SearchServiceV3",