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