google.golang.org/grpc@v1.62.1/reflection/serverreflection_test.go (about)

     1  /*
     2   *
     3   * Copyright 2016 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package reflection
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"net"
    25  	"reflect"
    26  	"sort"
    27  	"testing"
    28  	"time"
    29  
    30  	"google.golang.org/grpc"
    31  	"google.golang.org/grpc/credentials/insecure"
    32  	"google.golang.org/grpc/internal/grpctest"
    33  	"google.golang.org/protobuf/proto"
    34  	"google.golang.org/protobuf/reflect/protodesc"
    35  	"google.golang.org/protobuf/reflect/protoreflect"
    36  	"google.golang.org/protobuf/reflect/protoregistry"
    37  	"google.golang.org/protobuf/types/descriptorpb"
    38  	"google.golang.org/protobuf/types/dynamicpb"
    39  
    40  	v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
    41  	v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1"
    42  	v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
    43  	v1alphareflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
    44  	pb "google.golang.org/grpc/reflection/grpc_testing"
    45  	pbv3 "google.golang.org/grpc/reflection/grpc_testing_not_regenerate"
    46  )
    47  
    48  var (
    49  	s = NewServerV1(ServerOptions{}).(*serverReflectionServer)
    50  	// fileDescriptor of each test proto file.
    51  	fdProto2Ext  *descriptorpb.FileDescriptorProto
    52  	fdProto2Ext2 *descriptorpb.FileDescriptorProto
    53  	fdDynamic    *descriptorpb.FileDescriptorProto
    54  	// reflection descriptors.
    55  	fdDynamicFile protoreflect.FileDescriptor
    56  	// fileDescriptor marshalled.
    57  	fdTestByte       []byte
    58  	fdTestv3Byte     []byte
    59  	fdProto2Byte     []byte
    60  	fdProto2ExtByte  []byte
    61  	fdProto2Ext2Byte []byte
    62  	fdDynamicByte    []byte
    63  )
    64  
    65  const defaultTestTimeout = 10 * time.Second
    66  
    67  type x struct {
    68  	grpctest.Tester
    69  }
    70  
    71  func Test(t *testing.T) {
    72  	grpctest.RunSubTests(t, x{})
    73  }
    74  
    75  func loadFileDesc(filename string) (*descriptorpb.FileDescriptorProto, []byte) {
    76  	fd, err := protoregistry.GlobalFiles.FindFileByPath(filename)
    77  	if err != nil {
    78  		panic(err)
    79  	}
    80  	fdProto := protodesc.ToFileDescriptorProto(fd)
    81  	b, err := proto.Marshal(fdProto)
    82  	if err != nil {
    83  		panic(fmt.Sprintf("failed to marshal fd: %v", err))
    84  	}
    85  	return fdProto, b
    86  }
    87  
    88  func loadFileDescDynamic(b []byte) (*descriptorpb.FileDescriptorProto, protoreflect.FileDescriptor, []byte) {
    89  	m := new(descriptorpb.FileDescriptorProto)
    90  	if err := proto.Unmarshal(b, m); err != nil {
    91  		panic("failed to unmarshal dynamic proto raw descriptor")
    92  	}
    93  
    94  	fd, err := protodesc.NewFile(m, nil)
    95  	if err != nil {
    96  		panic(err)
    97  	}
    98  
    99  	err = protoregistry.GlobalFiles.RegisterFile(fd)
   100  	if err != nil {
   101  		panic(err)
   102  	}
   103  
   104  	for i := 0; i < fd.Messages().Len(); i++ {
   105  		m := fd.Messages().Get(i)
   106  		if err := protoregistry.GlobalTypes.RegisterMessage(dynamicpb.NewMessageType(m)); err != nil {
   107  			panic(err)
   108  		}
   109  	}
   110  
   111  	return m, fd, b
   112  }
   113  
   114  func init() {
   115  	_, fdTestByte = loadFileDesc("reflection/grpc_testing/test.proto")
   116  	_, fdTestv3Byte = loadFileDesc("testv3.proto")
   117  	_, fdProto2Byte = loadFileDesc("reflection/grpc_testing/proto2.proto")
   118  	fdProto2Ext, fdProto2ExtByte = loadFileDesc("reflection/grpc_testing/proto2_ext.proto")
   119  	fdProto2Ext2, fdProto2Ext2Byte = loadFileDesc("reflection/grpc_testing/proto2_ext2.proto")
   120  	fdDynamic, fdDynamicFile, fdDynamicByte = loadFileDescDynamic(pbv3.FileDynamicProtoRawDesc)
   121  }
   122  
   123  func (x) TestFileDescContainingExtension(t *testing.T) {
   124  	for _, test := range []struct {
   125  		st     string
   126  		extNum int32
   127  		want   *descriptorpb.FileDescriptorProto
   128  	}{
   129  		{"grpc.testing.ToBeExtended", 13, fdProto2Ext},
   130  		{"grpc.testing.ToBeExtended", 17, fdProto2Ext},
   131  		{"grpc.testing.ToBeExtended", 19, fdProto2Ext},
   132  		{"grpc.testing.ToBeExtended", 23, fdProto2Ext2},
   133  		{"grpc.testing.ToBeExtended", 29, fdProto2Ext2},
   134  	} {
   135  		fd, err := s.fileDescEncodingContainingExtension(test.st, test.extNum, map[string]bool{})
   136  		if err != nil {
   137  			t.Errorf("fileDescContainingExtension(%q) return error: %v", test.st, err)
   138  			continue
   139  		}
   140  		var actualFd descriptorpb.FileDescriptorProto
   141  		if err := proto.Unmarshal(fd[0], &actualFd); err != nil {
   142  			t.Errorf("fileDescContainingExtension(%q) return invalid bytes: %v", test.st, err)
   143  			continue
   144  		}
   145  		if !proto.Equal(&actualFd, test.want) {
   146  			t.Errorf("fileDescContainingExtension(%q) returned %q, but wanted %q", test.st, &actualFd, test.want)
   147  		}
   148  	}
   149  }
   150  
   151  // intArray is used to sort []int32
   152  type intArray []int32
   153  
   154  func (s intArray) Len() int           { return len(s) }
   155  func (s intArray) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   156  func (s intArray) Less(i, j int) bool { return s[i] < s[j] }
   157  
   158  func (x) TestAllExtensionNumbersForTypeName(t *testing.T) {
   159  	for _, test := range []struct {
   160  		st   string
   161  		want []int32
   162  	}{
   163  		{"grpc.testing.ToBeExtended", []int32{13, 17, 19, 23, 29}},
   164  	} {
   165  		r, err := s.allExtensionNumbersForTypeName(test.st)
   166  		sort.Sort(intArray(r))
   167  		if err != nil || !reflect.DeepEqual(r, test.want) {
   168  			t.Errorf("allExtensionNumbersForType(%q) = %v, %v, want %v, <nil>", test.st, r, err, test.want)
   169  		}
   170  	}
   171  }
   172  
   173  func (x) TestFileDescWithDependencies(t *testing.T) {
   174  	depFile, err := protodesc.NewFile(
   175  		&descriptorpb.FileDescriptorProto{
   176  			Name: proto.String("dep.proto"),
   177  		}, nil,
   178  	)
   179  	if err != nil {
   180  		t.Fatalf("unexpected error: %s", err)
   181  	}
   182  
   183  	deps := &protoregistry.Files{}
   184  	if err := deps.RegisterFile(depFile); err != nil {
   185  		t.Fatalf("unexpected error: %s", err)
   186  	}
   187  
   188  	rootFileProto := &descriptorpb.FileDescriptorProto{
   189  		Name: proto.String("root.proto"),
   190  		Dependency: []string{
   191  			"google/protobuf/descriptor.proto",
   192  			"reflection/grpc_testing/proto2_ext2.proto",
   193  			"dep.proto",
   194  		},
   195  	}
   196  
   197  	// dep.proto is in deps; the other imports come from protoregistry.GlobalFiles
   198  	resolver := &combinedResolver{first: protoregistry.GlobalFiles, second: deps}
   199  	rootFile, err := protodesc.NewFile(rootFileProto, resolver)
   200  	if err != nil {
   201  		t.Fatalf("unexpected error: %s", err)
   202  	}
   203  
   204  	// Create a file hierarchy that contains a placeholder for dep.proto
   205  	placeholderDep := placeholderFile{depFile}
   206  	placeholderDeps := &protoregistry.Files{}
   207  	if err := placeholderDeps.RegisterFile(placeholderDep); err != nil {
   208  		t.Fatalf("unexpected error: %s", err)
   209  	}
   210  	resolver = &combinedResolver{first: protoregistry.GlobalFiles, second: placeholderDeps}
   211  
   212  	rootFileHasPlaceholderDep, err := protodesc.NewFile(rootFileProto, resolver)
   213  	if err != nil {
   214  		t.Fatalf("unexpected error: %s", err)
   215  	}
   216  
   217  	rootFileIsPlaceholder := placeholderFile{rootFile}
   218  
   219  	// Full transitive dependency graph of root.proto includes five files:
   220  	// - root.proto
   221  	//   - google/protobuf/descriptor.proto
   222  	//   - reflection/grpc_testing/proto2_ext2.proto
   223  	//     - reflection/grpc_testing/proto2.proto
   224  	//   - dep.proto
   225  
   226  	for _, test := range []struct {
   227  		name   string
   228  		sent   []string
   229  		root   protoreflect.FileDescriptor
   230  		expect []string
   231  	}{
   232  		{
   233  			name: "send_all",
   234  			root: rootFile,
   235  			// expect full transitive closure
   236  			expect: []string{
   237  				"root.proto",
   238  				"google/protobuf/descriptor.proto",
   239  				"reflection/grpc_testing/proto2_ext2.proto",
   240  				"reflection/grpc_testing/proto2.proto",
   241  				"dep.proto",
   242  			},
   243  		},
   244  		{
   245  			name: "already_sent",
   246  			sent: []string{
   247  				"root.proto",
   248  				"google/protobuf/descriptor.proto",
   249  				"reflection/grpc_testing/proto2_ext2.proto",
   250  				"reflection/grpc_testing/proto2.proto",
   251  				"dep.proto",
   252  			},
   253  			root: rootFile,
   254  			// expect only the root to be re-sent
   255  			expect: []string{"root.proto"},
   256  		},
   257  		{
   258  			name: "some_already_sent",
   259  			sent: []string{
   260  				"reflection/grpc_testing/proto2_ext2.proto",
   261  				"reflection/grpc_testing/proto2.proto",
   262  			},
   263  			root: rootFile,
   264  			expect: []string{
   265  				"root.proto",
   266  				"google/protobuf/descriptor.proto",
   267  				"dep.proto",
   268  			},
   269  		},
   270  		{
   271  			name: "root_is_placeholder",
   272  			root: rootFileIsPlaceholder,
   273  			// expect error, no files
   274  		},
   275  		{
   276  			name: "placeholder_skipped",
   277  			root: rootFileHasPlaceholderDep,
   278  			// dep.proto is a placeholder so is skipped
   279  			expect: []string{
   280  				"root.proto",
   281  				"google/protobuf/descriptor.proto",
   282  				"reflection/grpc_testing/proto2_ext2.proto",
   283  				"reflection/grpc_testing/proto2.proto",
   284  			},
   285  		},
   286  		{
   287  			name: "placeholder_skipped_and_some_sent",
   288  			sent: []string{
   289  				"reflection/grpc_testing/proto2_ext2.proto",
   290  				"reflection/grpc_testing/proto2.proto",
   291  			},
   292  			root: rootFileHasPlaceholderDep,
   293  			expect: []string{
   294  				"root.proto",
   295  				"google/protobuf/descriptor.proto",
   296  			},
   297  		},
   298  	} {
   299  		t.Run(test.name, func(t *testing.T) {
   300  			s := NewServerV1(ServerOptions{}).(*serverReflectionServer)
   301  
   302  			sent := map[string]bool{}
   303  			for _, path := range test.sent {
   304  				sent[path] = true
   305  			}
   306  
   307  			descriptors, err := s.fileDescWithDependencies(test.root, sent)
   308  			if len(test.expect) == 0 {
   309  				// if we're not expecting any files then we're expecting an error
   310  				if err == nil {
   311  					t.Fatalf("expecting an error; instead got %d files", len(descriptors))
   312  				}
   313  				return
   314  			}
   315  
   316  			checkDescriptorResults(t, descriptors, test.expect)
   317  		})
   318  	}
   319  }
   320  
   321  func checkDescriptorResults(t *testing.T, descriptors [][]byte, expect []string) {
   322  	t.Helper()
   323  	if len(descriptors) != len(expect) {
   324  		t.Errorf("expected result to contain %d descriptor(s); instead got %d", len(expect), len(descriptors))
   325  	}
   326  	names := map[string]struct{}{}
   327  	for i, desc := range descriptors {
   328  		var descProto descriptorpb.FileDescriptorProto
   329  		if err := proto.Unmarshal(desc, &descProto); err != nil {
   330  			t.Fatalf("could not unmarshal descriptor result #%d", i+1)
   331  		}
   332  		names[descProto.GetName()] = struct{}{}
   333  	}
   334  	actual := make([]string, 0, len(names))
   335  	for name := range names {
   336  		actual = append(actual, name)
   337  	}
   338  	sort.Strings(actual)
   339  	sort.Strings(expect)
   340  	if !reflect.DeepEqual(actual, expect) {
   341  		t.Fatalf("expected file descriptors for %v; instead got %v", expect, actual)
   342  	}
   343  }
   344  
   345  type placeholderFile struct {
   346  	protoreflect.FileDescriptor
   347  }
   348  
   349  func (placeholderFile) IsPlaceholder() bool {
   350  	return true
   351  }
   352  
   353  type combinedResolver struct {
   354  	first, second protodesc.Resolver
   355  }
   356  
   357  func (r *combinedResolver) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
   358  	file, err := r.first.FindFileByPath(path)
   359  	if err == nil {
   360  		return file, nil
   361  	}
   362  	return r.second.FindFileByPath(path)
   363  }
   364  
   365  func (r *combinedResolver) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
   366  	desc, err := r.first.FindDescriptorByName(name)
   367  	if err == nil {
   368  		return desc, nil
   369  	}
   370  	return r.second.FindDescriptorByName(name)
   371  }
   372  
   373  // Do end2end tests.
   374  
   375  type server struct {
   376  	pb.UnimplementedSearchServiceServer
   377  }
   378  
   379  func (s *server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.SearchResponse, error) {
   380  	return &pb.SearchResponse{}, nil
   381  }
   382  
   383  func (s *server) StreamingSearch(stream pb.SearchService_StreamingSearchServer) error {
   384  	return nil
   385  }
   386  
   387  type serverV3 struct{}
   388  
   389  func (s *serverV3) Search(ctx context.Context, in *pbv3.SearchRequestV3) (*pbv3.SearchResponseV3, error) {
   390  	return &pbv3.SearchResponseV3{}, nil
   391  }
   392  
   393  func (s *serverV3) StreamingSearch(stream pbv3.SearchServiceV3_StreamingSearchServer) error {
   394  	return nil
   395  }
   396  
   397  func (x) TestReflectionEnd2end(t *testing.T) {
   398  	// Start server.
   399  	lis, err := net.Listen("tcp", "localhost:0")
   400  	if err != nil {
   401  		t.Fatalf("failed to listen: %v", err)
   402  	}
   403  	s := grpc.NewServer()
   404  	pb.RegisterSearchServiceServer(s, &server{})
   405  	pbv3.RegisterSearchServiceV3Server(s, &serverV3{})
   406  
   407  	registerDynamicProto(s, fdDynamic, fdDynamicFile)
   408  
   409  	// Register reflection service on s.
   410  	Register(s)
   411  	go s.Serve(lis)
   412  	t.Cleanup(s.Stop)
   413  
   414  	// Create client.
   415  	conn, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
   416  	if err != nil {
   417  		t.Fatalf("cannot connect to server: %v", err)
   418  	}
   419  	defer conn.Close()
   420  
   421  	clientV1 := v1reflectiongrpc.NewServerReflectionClient(conn)
   422  	clientV1Alpha := v1alphareflectiongrpc.NewServerReflectionClient(conn)
   423  	testCases := []struct {
   424  		name   string
   425  		client v1reflectiongrpc.ServerReflectionClient
   426  	}{
   427  		{
   428  			name:   "v1",
   429  			client: clientV1,
   430  		},
   431  		{
   432  			name:   "v1alpha",
   433  			client: v1AlphaClientAdapter{stub: clientV1Alpha},
   434  		},
   435  	}
   436  	for _, testCase := range testCases {
   437  		c := testCase.client
   438  		t.Run(testCase.name, func(t *testing.T) {
   439  			ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   440  			defer cancel()
   441  			stream, err := c.ServerReflectionInfo(ctx, grpc.WaitForReady(true))
   442  			if err != nil {
   443  				t.Fatalf("cannot get ServerReflectionInfo: %v", err)
   444  			}
   445  
   446  			testFileByFilenameTransitiveClosure(t, stream, true)
   447  			testFileByFilenameTransitiveClosure(t, stream, false)
   448  			testFileByFilename(t, stream)
   449  			testFileByFilenameError(t, stream)
   450  			testFileContainingSymbol(t, stream)
   451  			testFileContainingSymbolError(t, stream)
   452  			testFileContainingExtension(t, stream)
   453  			testFileContainingExtensionError(t, stream)
   454  			testAllExtensionNumbersOfType(t, stream)
   455  			testAllExtensionNumbersOfTypeError(t, stream)
   456  			testListServices(t, stream)
   457  		})
   458  	}
   459  }
   460  
   461  func testFileByFilenameTransitiveClosure(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient, expectClosure bool) {
   462  	filename := "reflection/grpc_testing/proto2_ext2.proto"
   463  	if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   464  		MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileByFilename{
   465  			FileByFilename: filename,
   466  		},
   467  	}); err != nil {
   468  		t.Fatalf("failed to send request: %v", err)
   469  	}
   470  	r, err := stream.Recv()
   471  	if err != nil {
   472  		// io.EOF is not ok.
   473  		t.Fatalf("failed to recv response: %v", err)
   474  	}
   475  	switch r.MessageResponse.(type) {
   476  	case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse:
   477  		if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) {
   478  			t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte)
   479  		}
   480  		if expectClosure {
   481  			if len(r.GetFileDescriptorResponse().FileDescriptorProto) != 2 {
   482  				t.Errorf("FileByFilename(%v) returned %v file descriptors, expected 2", filename, len(r.GetFileDescriptorResponse().FileDescriptorProto))
   483  			} else if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[1], fdProto2Byte) {
   484  				t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[1], fdProto2Byte)
   485  			}
   486  		} else if len(r.GetFileDescriptorResponse().FileDescriptorProto) != 1 {
   487  			t.Errorf("FileByFilename(%v) returned %v file descriptors, expected 1", filename, len(r.GetFileDescriptorResponse().FileDescriptorProto))
   488  		}
   489  	default:
   490  		t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", filename, r.MessageResponse)
   491  	}
   492  }
   493  
   494  func testFileByFilename(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   495  	for _, test := range []struct {
   496  		filename string
   497  		want     []byte
   498  	}{
   499  		{"reflection/grpc_testing/test.proto", fdTestByte},
   500  		{"reflection/grpc_testing/proto2.proto", fdProto2Byte},
   501  		{"reflection/grpc_testing/proto2_ext.proto", fdProto2ExtByte},
   502  		{"dynamic.proto", fdDynamicByte},
   503  	} {
   504  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   505  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileByFilename{
   506  				FileByFilename: test.filename,
   507  			},
   508  		}); err != nil {
   509  			t.Fatalf("failed to send request: %v", err)
   510  		}
   511  		r, err := stream.Recv()
   512  		if err != nil {
   513  			// io.EOF is not ok.
   514  			t.Fatalf("failed to recv response: %v", err)
   515  		}
   516  
   517  		switch r.MessageResponse.(type) {
   518  		case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse:
   519  			if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) {
   520  				t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", test.filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want)
   521  			}
   522  		default:
   523  			t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.filename, r.MessageResponse)
   524  		}
   525  	}
   526  }
   527  
   528  func testFileByFilenameError(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   529  	for _, test := range []string{
   530  		"test.poto",
   531  		"proo2.proto",
   532  		"proto2_et.proto",
   533  	} {
   534  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   535  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileByFilename{
   536  				FileByFilename: test,
   537  			},
   538  		}); err != nil {
   539  			t.Fatalf("failed to send request: %v", err)
   540  		}
   541  		r, err := stream.Recv()
   542  		if err != nil {
   543  			// io.EOF is not ok.
   544  			t.Fatalf("failed to recv response: %v", err)
   545  		}
   546  
   547  		switch r.MessageResponse.(type) {
   548  		case *v1reflectionpb.ServerReflectionResponse_ErrorResponse:
   549  		default:
   550  			t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
   551  		}
   552  	}
   553  }
   554  
   555  func testFileContainingSymbol(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   556  	for _, test := range []struct {
   557  		symbol string
   558  		want   []byte
   559  	}{
   560  		{"grpc.testing.SearchService", fdTestByte},
   561  		{"grpc.testing.SearchService.Search", fdTestByte},
   562  		{"grpc.testing.SearchService.StreamingSearch", fdTestByte},
   563  		{"grpc.testing.SearchResponse", fdTestByte},
   564  		{"grpc.testing.ToBeExtended", fdProto2Byte},
   565  		// Test support package v3.
   566  		{"grpc.testingv3.SearchServiceV3", fdTestv3Byte},
   567  		{"grpc.testingv3.SearchServiceV3.Search", fdTestv3Byte},
   568  		{"grpc.testingv3.SearchServiceV3.StreamingSearch", fdTestv3Byte},
   569  		{"grpc.testingv3.SearchResponseV3", fdTestv3Byte},
   570  		// search for field, oneof, enum, and enum value symbols, too
   571  		{"grpc.testingv3.SearchResponseV3.Result.snippets", fdTestv3Byte},
   572  		{"grpc.testingv3.SearchResponseV3.Result.Value.val", fdTestv3Byte},
   573  		{"grpc.testingv3.SearchResponseV3.Result.Value.str", fdTestv3Byte},
   574  		{"grpc.testingv3.SearchResponseV3.State", fdTestv3Byte},
   575  		{"grpc.testingv3.SearchResponseV3.FRESH", fdTestv3Byte},
   576  		// Test dynamic symbols
   577  		{"grpc.testing.DynamicService", fdDynamicByte},
   578  		{"grpc.testing.DynamicReq", fdDynamicByte},
   579  		{"grpc.testing.DynamicRes", fdDynamicByte},
   580  	} {
   581  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   582  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileContainingSymbol{
   583  				FileContainingSymbol: test.symbol,
   584  			},
   585  		}); err != nil {
   586  			t.Fatalf("failed to send request: %v", err)
   587  		}
   588  		r, err := stream.Recv()
   589  		if err != nil {
   590  			// io.EOF is not ok.
   591  			t.Fatalf("failed to recv response: %v", err)
   592  		}
   593  
   594  		switch r.MessageResponse.(type) {
   595  		case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse:
   596  			if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) {
   597  				t.Errorf("FileContainingSymbol(%v)\nreceived: %q,\nwant: %q", test.symbol, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want)
   598  			}
   599  		default:
   600  			t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.symbol, r.MessageResponse)
   601  		}
   602  	}
   603  }
   604  
   605  func testFileContainingSymbolError(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   606  	for _, test := range []string{
   607  		"grpc.testing.SerchService",
   608  		"grpc.testing.SearchService.SearchE",
   609  		"grpc.tesing.SearchResponse",
   610  		"gpc.testing.ToBeExtended",
   611  	} {
   612  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   613  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileContainingSymbol{
   614  				FileContainingSymbol: test,
   615  			},
   616  		}); err != nil {
   617  			t.Fatalf("failed to send request: %v", err)
   618  		}
   619  		r, err := stream.Recv()
   620  		if err != nil {
   621  			// io.EOF is not ok.
   622  			t.Fatalf("failed to recv response: %v", err)
   623  		}
   624  
   625  		switch r.MessageResponse.(type) {
   626  		case *v1reflectionpb.ServerReflectionResponse_ErrorResponse:
   627  		default:
   628  			t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
   629  		}
   630  	}
   631  }
   632  
   633  func testFileContainingExtension(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   634  	for _, test := range []struct {
   635  		typeName string
   636  		extNum   int32
   637  		want     []byte
   638  	}{
   639  		{"grpc.testing.ToBeExtended", 13, fdProto2ExtByte},
   640  		{"grpc.testing.ToBeExtended", 17, fdProto2ExtByte},
   641  		{"grpc.testing.ToBeExtended", 19, fdProto2ExtByte},
   642  		{"grpc.testing.ToBeExtended", 23, fdProto2Ext2Byte},
   643  		{"grpc.testing.ToBeExtended", 29, fdProto2Ext2Byte},
   644  	} {
   645  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   646  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileContainingExtension{
   647  				FileContainingExtension: &v1reflectionpb.ExtensionRequest{
   648  					ContainingType:  test.typeName,
   649  					ExtensionNumber: test.extNum,
   650  				},
   651  			},
   652  		}); err != nil {
   653  			t.Fatalf("failed to send request: %v", err)
   654  		}
   655  		r, err := stream.Recv()
   656  		if err != nil {
   657  			// io.EOF is not ok.
   658  			t.Fatalf("failed to recv response: %v", err)
   659  		}
   660  
   661  		switch r.MessageResponse.(type) {
   662  		case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse:
   663  			if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) {
   664  				t.Errorf("FileContainingExtension(%v, %v)\nreceived: %q,\nwant: %q", test.typeName, test.extNum, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want)
   665  			}
   666  		default:
   667  			t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse)
   668  		}
   669  	}
   670  }
   671  
   672  func testFileContainingExtensionError(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   673  	for _, test := range []struct {
   674  		typeName string
   675  		extNum   int32
   676  	}{
   677  		{"grpc.testing.ToBExtended", 17},
   678  		{"grpc.testing.ToBeExtended", 15},
   679  	} {
   680  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   681  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_FileContainingExtension{
   682  				FileContainingExtension: &v1reflectionpb.ExtensionRequest{
   683  					ContainingType:  test.typeName,
   684  					ExtensionNumber: test.extNum,
   685  				},
   686  			},
   687  		}); err != nil {
   688  			t.Fatalf("failed to send request: %v", err)
   689  		}
   690  		r, err := stream.Recv()
   691  		if err != nil {
   692  			// io.EOF is not ok.
   693  			t.Fatalf("failed to recv response: %v", err)
   694  		}
   695  
   696  		switch r.MessageResponse.(type) {
   697  		case *v1reflectionpb.ServerReflectionResponse_ErrorResponse:
   698  		default:
   699  			t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse)
   700  		}
   701  	}
   702  }
   703  
   704  func testAllExtensionNumbersOfType(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   705  	for _, test := range []struct {
   706  		typeName string
   707  		want     []int32
   708  	}{
   709  		{"grpc.testing.ToBeExtended", []int32{13, 17, 19, 23, 29}},
   710  		{"grpc.testing.DynamicReq", nil},
   711  	} {
   712  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   713  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{
   714  				AllExtensionNumbersOfType: test.typeName,
   715  			},
   716  		}); err != nil {
   717  			t.Fatalf("failed to send request: %v", err)
   718  		}
   719  		r, err := stream.Recv()
   720  		if err != nil {
   721  			// io.EOF is not ok.
   722  			t.Fatalf("failed to recv response: %v", err)
   723  		}
   724  
   725  		switch r.MessageResponse.(type) {
   726  		case *v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse:
   727  			extNum := r.GetAllExtensionNumbersResponse().ExtensionNumber
   728  			sort.Sort(intArray(extNum))
   729  			if r.GetAllExtensionNumbersResponse().BaseTypeName != test.typeName ||
   730  				!reflect.DeepEqual(extNum, test.want) {
   731  				t.Errorf("AllExtensionNumbersOfType(%v)\nreceived: %v,\nwant: {%q %v}", r.GetAllExtensionNumbersResponse(), test.typeName, test.typeName, test.want)
   732  			}
   733  		default:
   734  			t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_AllExtensionNumbersResponse>", test.typeName, r.MessageResponse)
   735  		}
   736  	}
   737  }
   738  
   739  func testAllExtensionNumbersOfTypeError(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   740  	for _, test := range []string{
   741  		"grpc.testing.ToBeExtendedE",
   742  	} {
   743  		if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   744  			MessageRequest: &v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{
   745  				AllExtensionNumbersOfType: test,
   746  			},
   747  		}); err != nil {
   748  			t.Fatalf("failed to send request: %v", err)
   749  		}
   750  		r, err := stream.Recv()
   751  		if err != nil {
   752  			// io.EOF is not ok.
   753  			t.Fatalf("failed to recv response: %v", err)
   754  		}
   755  
   756  		switch r.MessageResponse.(type) {
   757  		case *v1reflectionpb.ServerReflectionResponse_ErrorResponse:
   758  		default:
   759  			t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse)
   760  		}
   761  	}
   762  }
   763  
   764  func testListServices(t *testing.T, stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient) {
   765  	if err := stream.Send(&v1reflectionpb.ServerReflectionRequest{
   766  		MessageRequest: &v1reflectionpb.ServerReflectionRequest_ListServices{},
   767  	}); err != nil {
   768  		t.Fatalf("failed to send request: %v", err)
   769  	}
   770  	r, err := stream.Recv()
   771  	if err != nil {
   772  		// io.EOF is not ok.
   773  		t.Fatalf("failed to recv response: %v", err)
   774  	}
   775  
   776  	switch r.MessageResponse.(type) {
   777  	case *v1reflectionpb.ServerReflectionResponse_ListServicesResponse:
   778  		services := r.GetListServicesResponse().Service
   779  		want := []string{
   780  			"grpc.testingv3.SearchServiceV3",
   781  			"grpc.testing.SearchService",
   782  			"grpc.reflection.v1.ServerReflection",
   783  			"grpc.reflection.v1alpha.ServerReflection",
   784  			"grpc.testing.DynamicService",
   785  		}
   786  		// Compare service names in response with want.
   787  		if len(services) != len(want) {
   788  			t.Errorf("= %v, want service names: %v", services, want)
   789  		}
   790  		m := make(map[string]int)
   791  		for _, e := range services {
   792  			m[e.Name]++
   793  		}
   794  		for _, e := range want {
   795  			if m[e] > 0 {
   796  				m[e]--
   797  				continue
   798  			}
   799  			t.Errorf("ListService\nreceived: %v,\nwant: %q", services, want)
   800  		}
   801  	default:
   802  		t.Errorf("ListServices = %v, want type <ServerReflectionResponse_ListServicesResponse>", r.MessageResponse)
   803  	}
   804  }
   805  
   806  func registerDynamicProto(srv *grpc.Server, fdp *descriptorpb.FileDescriptorProto, fd protoreflect.FileDescriptor) {
   807  	type emptyInterface any
   808  
   809  	for i := 0; i < fd.Services().Len(); i++ {
   810  		s := fd.Services().Get(i)
   811  
   812  		sd := &grpc.ServiceDesc{
   813  			ServiceName: string(s.FullName()),
   814  			HandlerType: (*emptyInterface)(nil),
   815  			Metadata:    fdp.GetName(),
   816  		}
   817  
   818  		for j := 0; j < s.Methods().Len(); j++ {
   819  			m := s.Methods().Get(j)
   820  			sd.Methods = append(sd.Methods, grpc.MethodDesc{
   821  				MethodName: string(m.Name()),
   822  			})
   823  		}
   824  
   825  		srv.RegisterService(sd, struct{}{})
   826  	}
   827  }
   828  
   829  type v1AlphaClientAdapter struct {
   830  	stub v1alphareflectiongrpc.ServerReflectionClient
   831  }
   832  
   833  func (v v1AlphaClientAdapter) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (v1reflectiongrpc.ServerReflection_ServerReflectionInfoClient, error) {
   834  	stream, err := v.stub.ServerReflectionInfo(ctx, opts...)
   835  	if err != nil {
   836  		return nil, err
   837  	}
   838  	return v1AlphaClientStreamAdapter{stream}, nil
   839  }
   840  
   841  type v1AlphaClientStreamAdapter struct {
   842  	v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoClient
   843  }
   844  
   845  func (s v1AlphaClientStreamAdapter) Send(request *v1reflectionpb.ServerReflectionRequest) error {
   846  	return s.ServerReflection_ServerReflectionInfoClient.Send(v1ToV1AlphaRequest(request))
   847  }
   848  
   849  func (s v1AlphaClientStreamAdapter) Recv() (*v1reflectionpb.ServerReflectionResponse, error) {
   850  	resp, err := s.ServerReflection_ServerReflectionInfoClient.Recv()
   851  	if err != nil {
   852  		return nil, err
   853  	}
   854  	return v1AlphaToV1Response(resp), nil
   855  }
   856  
   857  func v1AlphaToV1Response(v1alpha *v1alphareflectionpb.ServerReflectionResponse) *v1reflectionpb.ServerReflectionResponse {
   858  	var v1 v1reflectionpb.ServerReflectionResponse
   859  	v1.ValidHost = v1alpha.ValidHost
   860  	if v1alpha.OriginalRequest != nil {
   861  		v1.OriginalRequest = v1AlphaToV1Request(v1alpha.OriginalRequest)
   862  	}
   863  	switch mr := v1alpha.MessageResponse.(type) {
   864  	case *v1alphareflectionpb.ServerReflectionResponse_FileDescriptorResponse:
   865  		if mr != nil {
   866  			v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{
   867  				FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{
   868  					FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(),
   869  				},
   870  			}
   871  		}
   872  	case *v1alphareflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse:
   873  		if mr != nil {
   874  			v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{
   875  				AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{
   876  					BaseTypeName:    mr.AllExtensionNumbersResponse.GetBaseTypeName(),
   877  					ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(),
   878  				},
   879  			}
   880  		}
   881  	case *v1alphareflectionpb.ServerReflectionResponse_ListServicesResponse:
   882  		if mr != nil {
   883  			svcs := make([]*v1reflectionpb.ServiceResponse, len(mr.ListServicesResponse.GetService()))
   884  			for i, svc := range mr.ListServicesResponse.GetService() {
   885  				svcs[i] = &v1reflectionpb.ServiceResponse{
   886  					Name: svc.GetName(),
   887  				}
   888  			}
   889  			v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{
   890  				ListServicesResponse: &v1reflectionpb.ListServiceResponse{
   891  					Service: svcs,
   892  				},
   893  			}
   894  		}
   895  	case *v1alphareflectionpb.ServerReflectionResponse_ErrorResponse:
   896  		if mr != nil {
   897  			v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{
   898  				ErrorResponse: &v1reflectionpb.ErrorResponse{
   899  					ErrorCode:    mr.ErrorResponse.GetErrorCode(),
   900  					ErrorMessage: mr.ErrorResponse.GetErrorMessage(),
   901  				},
   902  			}
   903  		}
   904  	default:
   905  		// no value set
   906  	}
   907  	return &v1
   908  }