gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/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 grpc "gitee.com/ks-custle/core-gm/grpc" 31 "gitee.com/ks-custle/core-gm/grpc/internal/grpctest" 32 rpb "gitee.com/ks-custle/core-gm/grpc/reflection/grpc_reflection_v1alpha" 33 pb "gitee.com/ks-custle/core-gm/grpc/reflection/grpc_testing" 34 pbv3 "gitee.com/ks-custle/core-gm/grpc/reflection/grpc_testingv3" 35 "github.com/golang/protobuf/proto" 36 dpb "github.com/golang/protobuf/protoc-gen-go/descriptor" 37 ) 38 39 var ( 40 s = &serverReflectionServer{} 41 // fileDescriptor of each test proto file. 42 fdTest *dpb.FileDescriptorProto 43 fdTestv3 *dpb.FileDescriptorProto 44 fdProto2 *dpb.FileDescriptorProto 45 fdProto2Ext *dpb.FileDescriptorProto 46 fdProto2Ext2 *dpb.FileDescriptorProto 47 // fileDescriptor marshalled. 48 fdTestByte []byte 49 fdTestv3Byte []byte 50 fdProto2Byte []byte 51 fdProto2ExtByte []byte 52 fdProto2Ext2Byte []byte 53 ) 54 55 const defaultTestTimeout = 10 * time.Second 56 57 type x struct { 58 grpctest.Tester 59 } 60 61 func Test(t *testing.T) { 62 grpctest.RunSubTests(t, x{}) 63 } 64 65 func loadFileDesc(filename string) (*dpb.FileDescriptorProto, []byte) { 66 enc := proto.FileDescriptor(filename) 67 if enc == nil { 68 panic(fmt.Sprintf("failed to find fd for file: %v", filename)) 69 } 70 fd, err := decodeFileDesc(enc) 71 if err != nil { 72 panic(fmt.Sprintf("failed to decode enc: %v", err)) 73 } 74 b, err := proto.Marshal(fd) 75 if err != nil { 76 panic(fmt.Sprintf("failed to marshal fd: %v", err)) 77 } 78 return fd, b 79 } 80 81 func init() { 82 fdTest, fdTestByte = loadFileDesc("reflection/grpc_testing/test.proto") 83 fdTestv3, fdTestv3Byte = loadFileDesc("testv3.proto") 84 fdProto2, fdProto2Byte = loadFileDesc("reflection/grpc_testing/proto2.proto") 85 fdProto2Ext, fdProto2ExtByte = loadFileDesc("reflection/grpc_testing/proto2_ext.proto") 86 fdProto2Ext2, fdProto2Ext2Byte = loadFileDesc("reflection/grpc_testing/proto2_ext2.proto") 87 } 88 89 func (x) TestFileDescForType(t *testing.T) { 90 for _, test := range []struct { 91 st reflect.Type 92 wantFd *dpb.FileDescriptorProto 93 }{ 94 {reflect.TypeOf(pb.SearchResponse_Result{}), fdTest}, 95 {reflect.TypeOf(pb.ToBeExtended{}), fdProto2}, 96 } { 97 fd, err := s.fileDescForType(test.st) 98 if err != nil || !proto.Equal(fd, test.wantFd) { 99 t.Errorf("fileDescForType(%q) = %q, %v, want %q, <nil>", test.st, fd, err, test.wantFd) 100 } 101 } 102 } 103 104 func (x) TestTypeForName(t *testing.T) { 105 for _, test := range []struct { 106 name string 107 want reflect.Type 108 }{ 109 {"grpc.testing.SearchResponse", reflect.TypeOf(pb.SearchResponse{})}, 110 } { 111 r, err := typeForName(test.name) 112 if err != nil || r != test.want { 113 t.Errorf("typeForName(%q) = %q, %v, want %q, <nil>", test.name, r, err, test.want) 114 } 115 } 116 } 117 118 func (x) TestTypeForNameNotFound(t *testing.T) { 119 for _, test := range []string{ 120 "grpc.testing.not_exiting", 121 } { 122 _, err := typeForName(test) 123 if err == nil { 124 t.Errorf("typeForName(%q) = _, %v, want _, <non-nil>", test, err) 125 } 126 } 127 } 128 129 func (x) TestFileDescContainingExtension(t *testing.T) { 130 for _, test := range []struct { 131 st reflect.Type 132 extNum int32 133 want *dpb.FileDescriptorProto 134 }{ 135 {reflect.TypeOf(pb.ToBeExtended{}), 13, fdProto2Ext}, 136 {reflect.TypeOf(pb.ToBeExtended{}), 17, fdProto2Ext}, 137 {reflect.TypeOf(pb.ToBeExtended{}), 19, fdProto2Ext}, 138 {reflect.TypeOf(pb.ToBeExtended{}), 23, fdProto2Ext2}, 139 {reflect.TypeOf(pb.ToBeExtended{}), 29, fdProto2Ext2}, 140 } { 141 fd, err := fileDescContainingExtension(test.st, test.extNum) 142 if err != nil || !proto.Equal(fd, test.want) { 143 t.Errorf("fileDescContainingExtension(%q) = %q, %v, want %q, <nil>", test.st, fd, err, test.want) 144 } 145 } 146 } 147 148 // intArray is used to sort []int32 149 type intArray []int32 150 151 func (s intArray) Len() int { return len(s) } 152 func (s intArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 153 func (s intArray) Less(i, j int) bool { return s[i] < s[j] } 154 155 func (x) TestAllExtensionNumbersForType(t *testing.T) { 156 for _, test := range []struct { 157 st reflect.Type 158 want []int32 159 }{ 160 {reflect.TypeOf(pb.ToBeExtended{}), []int32{13, 17, 19, 23, 29}}, 161 } { 162 r, err := s.allExtensionNumbersForType(test.st) 163 sort.Sort(intArray(r)) 164 if err != nil || !reflect.DeepEqual(r, test.want) { 165 t.Errorf("allExtensionNumbersForType(%q) = %v, %v, want %v, <nil>", test.st, r, err, test.want) 166 } 167 } 168 } 169 170 // Do end2end tests. 171 172 type server struct { 173 pb.UnimplementedSearchServiceServer 174 } 175 176 func (s *server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.SearchResponse, error) { 177 return &pb.SearchResponse{}, nil 178 } 179 180 func (s *server) StreamingSearch(stream pb.SearchService_StreamingSearchServer) error { 181 return nil 182 } 183 184 type serverV3 struct{} 185 186 func (s *serverV3) Search(ctx context.Context, in *pbv3.SearchRequestV3) (*pbv3.SearchResponseV3, error) { 187 return &pbv3.SearchResponseV3{}, nil 188 } 189 190 func (s *serverV3) StreamingSearch(stream pbv3.SearchServiceV3_StreamingSearchServer) error { 191 return nil 192 } 193 194 func (x) TestReflectionEnd2end(t *testing.T) { 195 // Start server. 196 lis, err := net.Listen("tcp", "localhost:0") 197 if err != nil { 198 t.Fatalf("failed to listen: %v", err) 199 } 200 s := grpc.NewServer() 201 pb.RegisterSearchServiceServer(s, &server{}) 202 pbv3.RegisterSearchServiceV3Server(s, &serverV3{}) 203 // Register reflection service on s. 204 Register(s) 205 go s.Serve(lis) 206 207 // Create client. 208 conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure()) 209 if err != nil { 210 t.Fatalf("cannot connect to server: %v", err) 211 } 212 defer conn.Close() 213 214 c := rpb.NewServerReflectionClient(conn) 215 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 216 defer cancel() 217 stream, err := c.ServerReflectionInfo(ctx, grpc.WaitForReady(true)) 218 if err != nil { 219 t.Fatalf("cannot get ServerReflectionInfo: %v", err) 220 } 221 222 testFileByFilenameTransitiveClosure(t, stream, true) 223 testFileByFilenameTransitiveClosure(t, stream, false) 224 testFileByFilename(t, stream) 225 testFileByFilenameError(t, stream) 226 testFileContainingSymbol(t, stream) 227 testFileContainingSymbolError(t, stream) 228 testFileContainingExtension(t, stream) 229 testFileContainingExtensionError(t, stream) 230 testAllExtensionNumbersOfType(t, stream) 231 testAllExtensionNumbersOfTypeError(t, stream) 232 testListServices(t, stream) 233 234 s.Stop() 235 } 236 237 func testFileByFilenameTransitiveClosure(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient, expectClosure bool) { 238 filename := "reflection/grpc_testing/proto2_ext2.proto" 239 if err := stream.Send(&rpb.ServerReflectionRequest{ 240 MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{ 241 FileByFilename: filename, 242 }, 243 }); err != nil { 244 t.Fatalf("failed to send request: %v", err) 245 } 246 r, err := stream.Recv() 247 if err != nil { 248 // io.EOF is not ok. 249 t.Fatalf("failed to recv response: %v", err) 250 } 251 switch r.MessageResponse.(type) { 252 case *rpb.ServerReflectionResponse_FileDescriptorResponse: 253 if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) { 254 t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], fdProto2Ext2Byte) 255 } 256 if expectClosure { 257 if len(r.GetFileDescriptorResponse().FileDescriptorProto) != 2 { 258 t.Errorf("FileByFilename(%v) returned %v file descriptors, expected 2", filename, len(r.GetFileDescriptorResponse().FileDescriptorProto)) 259 } else if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[1], fdProto2Byte) { 260 t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", filename, r.GetFileDescriptorResponse().FileDescriptorProto[1], fdProto2Byte) 261 } 262 } else if len(r.GetFileDescriptorResponse().FileDescriptorProto) != 1 { 263 t.Errorf("FileByFilename(%v) returned %v file descriptors, expected 1", filename, len(r.GetFileDescriptorResponse().FileDescriptorProto)) 264 } 265 default: 266 t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", filename, r.MessageResponse) 267 } 268 } 269 270 func testFileByFilename(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 271 for _, test := range []struct { 272 filename string 273 want []byte 274 }{ 275 {"reflection/grpc_testing/test.proto", fdTestByte}, 276 {"reflection/grpc_testing/proto2.proto", fdProto2Byte}, 277 {"reflection/grpc_testing/proto2_ext.proto", fdProto2ExtByte}, 278 } { 279 if err := stream.Send(&rpb.ServerReflectionRequest{ 280 MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{ 281 FileByFilename: test.filename, 282 }, 283 }); err != nil { 284 t.Fatalf("failed to send request: %v", err) 285 } 286 r, err := stream.Recv() 287 if err != nil { 288 // io.EOF is not ok. 289 t.Fatalf("failed to recv response: %v", err) 290 } 291 292 switch r.MessageResponse.(type) { 293 case *rpb.ServerReflectionResponse_FileDescriptorResponse: 294 if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { 295 t.Errorf("FileByFilename(%v)\nreceived: %q,\nwant: %q", test.filename, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) 296 } 297 default: 298 t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.filename, r.MessageResponse) 299 } 300 } 301 } 302 303 func testFileByFilenameError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 304 for _, test := range []string{ 305 "test.poto", 306 "proo2.proto", 307 "proto2_et.proto", 308 } { 309 if err := stream.Send(&rpb.ServerReflectionRequest{ 310 MessageRequest: &rpb.ServerReflectionRequest_FileByFilename{ 311 FileByFilename: test, 312 }, 313 }); err != nil { 314 t.Fatalf("failed to send request: %v", err) 315 } 316 r, err := stream.Recv() 317 if err != nil { 318 // io.EOF is not ok. 319 t.Fatalf("failed to recv response: %v", err) 320 } 321 322 switch r.MessageResponse.(type) { 323 case *rpb.ServerReflectionResponse_ErrorResponse: 324 default: 325 t.Errorf("FileByFilename(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse) 326 } 327 } 328 } 329 330 func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 331 for _, test := range []struct { 332 symbol string 333 want []byte 334 }{ 335 {"grpc.testing.SearchService", fdTestByte}, 336 {"grpc.testing.SearchService.Search", fdTestByte}, 337 {"grpc.testing.SearchService.StreamingSearch", fdTestByte}, 338 {"grpc.testing.SearchResponse", fdTestByte}, 339 {"grpc.testing.ToBeExtended", fdProto2Byte}, 340 // Test support package v3. 341 {"grpc.testingv3.SearchServiceV3", fdTestv3Byte}, 342 {"grpc.testingv3.SearchServiceV3.Search", fdTestv3Byte}, 343 {"grpc.testingv3.SearchServiceV3.StreamingSearch", fdTestv3Byte}, 344 {"grpc.testingv3.SearchResponseV3", fdTestv3Byte}, 345 // search for field, oneof, enum, and enum value symbols, too 346 {"grpc.testingv3.SearchResponseV3.Result.snippets", fdTestv3Byte}, 347 {"grpc.testingv3.SearchResponseV3.Result.Value.val", fdTestv3Byte}, 348 {"grpc.testingv3.SearchResponseV3.Result.Value.str", fdTestv3Byte}, 349 {"grpc.testingv3.SearchResponseV3.State", fdTestv3Byte}, 350 {"grpc.testingv3.SearchResponseV3.State.FRESH", fdTestv3Byte}, 351 } { 352 if err := stream.Send(&rpb.ServerReflectionRequest{ 353 MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{ 354 FileContainingSymbol: test.symbol, 355 }, 356 }); err != nil { 357 t.Fatalf("failed to send request: %v", err) 358 } 359 r, err := stream.Recv() 360 if err != nil { 361 // io.EOF is not ok. 362 t.Fatalf("failed to recv response: %v", err) 363 } 364 365 switch r.MessageResponse.(type) { 366 case *rpb.ServerReflectionResponse_FileDescriptorResponse: 367 if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { 368 t.Errorf("FileContainingSymbol(%v)\nreceived: %q,\nwant: %q", test.symbol, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) 369 } 370 default: 371 t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.symbol, r.MessageResponse) 372 } 373 } 374 } 375 376 func testFileContainingSymbolError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 377 for _, test := range []string{ 378 "grpc.testing.SerchService", 379 "grpc.testing.SearchService.SearchE", 380 "grpc.tesing.SearchResponse", 381 "gpc.testing.ToBeExtended", 382 } { 383 if err := stream.Send(&rpb.ServerReflectionRequest{ 384 MessageRequest: &rpb.ServerReflectionRequest_FileContainingSymbol{ 385 FileContainingSymbol: test, 386 }, 387 }); err != nil { 388 t.Fatalf("failed to send request: %v", err) 389 } 390 r, err := stream.Recv() 391 if err != nil { 392 // io.EOF is not ok. 393 t.Fatalf("failed to recv response: %v", err) 394 } 395 396 switch r.MessageResponse.(type) { 397 case *rpb.ServerReflectionResponse_ErrorResponse: 398 default: 399 t.Errorf("FileContainingSymbol(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse) 400 } 401 } 402 } 403 404 func testFileContainingExtension(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 405 for _, test := range []struct { 406 typeName string 407 extNum int32 408 want []byte 409 }{ 410 {"grpc.testing.ToBeExtended", 13, fdProto2ExtByte}, 411 {"grpc.testing.ToBeExtended", 17, fdProto2ExtByte}, 412 {"grpc.testing.ToBeExtended", 19, fdProto2ExtByte}, 413 {"grpc.testing.ToBeExtended", 23, fdProto2Ext2Byte}, 414 {"grpc.testing.ToBeExtended", 29, fdProto2Ext2Byte}, 415 } { 416 if err := stream.Send(&rpb.ServerReflectionRequest{ 417 MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{ 418 FileContainingExtension: &rpb.ExtensionRequest{ 419 ContainingType: test.typeName, 420 ExtensionNumber: test.extNum, 421 }, 422 }, 423 }); err != nil { 424 t.Fatalf("failed to send request: %v", err) 425 } 426 r, err := stream.Recv() 427 if err != nil { 428 // io.EOF is not ok. 429 t.Fatalf("failed to recv response: %v", err) 430 } 431 432 switch r.MessageResponse.(type) { 433 case *rpb.ServerReflectionResponse_FileDescriptorResponse: 434 if !reflect.DeepEqual(r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) { 435 t.Errorf("FileContainingExtension(%v, %v)\nreceived: %q,\nwant: %q", test.typeName, test.extNum, r.GetFileDescriptorResponse().FileDescriptorProto[0], test.want) 436 } 437 default: 438 t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse) 439 } 440 } 441 } 442 443 func testFileContainingExtensionError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 444 for _, test := range []struct { 445 typeName string 446 extNum int32 447 }{ 448 {"grpc.testing.ToBExtended", 17}, 449 {"grpc.testing.ToBeExtended", 15}, 450 } { 451 if err := stream.Send(&rpb.ServerReflectionRequest{ 452 MessageRequest: &rpb.ServerReflectionRequest_FileContainingExtension{ 453 FileContainingExtension: &rpb.ExtensionRequest{ 454 ContainingType: test.typeName, 455 ExtensionNumber: test.extNum, 456 }, 457 }, 458 }); err != nil { 459 t.Fatalf("failed to send request: %v", err) 460 } 461 r, err := stream.Recv() 462 if err != nil { 463 // io.EOF is not ok. 464 t.Fatalf("failed to recv response: %v", err) 465 } 466 467 switch r.MessageResponse.(type) { 468 case *rpb.ServerReflectionResponse_ErrorResponse: 469 default: 470 t.Errorf("FileContainingExtension(%v, %v) = %v, want type <ServerReflectionResponse_FileDescriptorResponse>", test.typeName, test.extNum, r.MessageResponse) 471 } 472 } 473 } 474 475 func testAllExtensionNumbersOfType(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 476 for _, test := range []struct { 477 typeName string 478 want []int32 479 }{ 480 {"grpc.testing.ToBeExtended", []int32{13, 17, 19, 23, 29}}, 481 } { 482 if err := stream.Send(&rpb.ServerReflectionRequest{ 483 MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{ 484 AllExtensionNumbersOfType: test.typeName, 485 }, 486 }); err != nil { 487 t.Fatalf("failed to send request: %v", err) 488 } 489 r, err := stream.Recv() 490 if err != nil { 491 // io.EOF is not ok. 492 t.Fatalf("failed to recv response: %v", err) 493 } 494 495 switch r.MessageResponse.(type) { 496 case *rpb.ServerReflectionResponse_AllExtensionNumbersResponse: 497 extNum := r.GetAllExtensionNumbersResponse().ExtensionNumber 498 sort.Sort(intArray(extNum)) 499 if r.GetAllExtensionNumbersResponse().BaseTypeName != test.typeName || 500 !reflect.DeepEqual(extNum, test.want) { 501 t.Errorf("AllExtensionNumbersOfType(%v)\nreceived: %v,\nwant: {%q %v}", r.GetAllExtensionNumbersResponse(), test.typeName, test.typeName, test.want) 502 } 503 default: 504 t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_AllExtensionNumbersResponse>", test.typeName, r.MessageResponse) 505 } 506 } 507 } 508 509 func testAllExtensionNumbersOfTypeError(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 510 for _, test := range []string{ 511 "grpc.testing.ToBeExtendedE", 512 } { 513 if err := stream.Send(&rpb.ServerReflectionRequest{ 514 MessageRequest: &rpb.ServerReflectionRequest_AllExtensionNumbersOfType{ 515 AllExtensionNumbersOfType: test, 516 }, 517 }); err != nil { 518 t.Fatalf("failed to send request: %v", err) 519 } 520 r, err := stream.Recv() 521 if err != nil { 522 // io.EOF is not ok. 523 t.Fatalf("failed to recv response: %v", err) 524 } 525 526 switch r.MessageResponse.(type) { 527 case *rpb.ServerReflectionResponse_ErrorResponse: 528 default: 529 t.Errorf("AllExtensionNumbersOfType(%v) = %v, want type <ServerReflectionResponse_ErrorResponse>", test, r.MessageResponse) 530 } 531 } 532 } 533 534 func testListServices(t *testing.T, stream rpb.ServerReflection_ServerReflectionInfoClient) { 535 if err := stream.Send(&rpb.ServerReflectionRequest{ 536 MessageRequest: &rpb.ServerReflectionRequest_ListServices{}, 537 }); err != nil { 538 t.Fatalf("failed to send request: %v", err) 539 } 540 r, err := stream.Recv() 541 if err != nil { 542 // io.EOF is not ok. 543 t.Fatalf("failed to recv response: %v", err) 544 } 545 546 switch r.MessageResponse.(type) { 547 case *rpb.ServerReflectionResponse_ListServicesResponse: 548 services := r.GetListServicesResponse().Service 549 want := []string{ 550 "grpc.testingv3.SearchServiceV3", 551 "grpc.testing.SearchService", 552 "grpc.reflection.v1alpha.ServerReflection", 553 } 554 // Compare service names in response with want. 555 if len(services) != len(want) { 556 t.Errorf("= %v, want service names: %v", services, want) 557 } 558 m := make(map[string]int) 559 for _, e := range services { 560 m[e.Name]++ 561 } 562 for _, e := range want { 563 if m[e] > 0 { 564 m[e]-- 565 continue 566 } 567 t.Errorf("ListService\nreceived: %v,\nwant: %q", services, want) 568 } 569 default: 570 t.Errorf("ListServices = %v, want type <ServerReflectionResponse_ListServicesResponse>", r.MessageResponse) 571 } 572 }