diff --git a/reflection/serverreflection.go b/reflection/serverreflection.go index 4f434531..e0857e56 100644 --- a/reflection/serverreflection.go +++ b/reflection/serverreflection.go @@ -87,3 +87,45 @@ func decompress(b []byte) []byte { } return out } + +func (s *serverReflectionServer) typeForName(name string) (reflect.Type, error) { + // TODO cache + + pt := proto.MessageType(name) + if pt == nil { + return nil, fmt.Errorf("unknown type: %q", name) + } + st := pt.Elem() + // TODO cache + // s.typeToNameMap[st] = name + // s.nameToTypeMap[name] = st + // fd, _, ok := s.fileDescForType(st) + // if ok { + // s.typeToFilenameMap[st] = fd.GetName() + // } + return st, nil +} + +func (s *serverReflectionServer) nameForType(st reflect.Type) (string, error) { + // TODO cache + + var name string + fd, idxs, err := s.fileDescForType(st) + if err != nil { + return "", err + } + mt := fd.MessageType[idxs[0]] + name = mt.GetName() + for i := 1; i < len(idxs); i++ { + mt = mt.NestedType[idxs[i]] + name += "_" + mt.GetName() + } + if fd.Package != nil { + name = *fd.Package + "." + name + } + return name, nil +} + +func (s *serverReflectionServer) nameForPointer(i interface{}) (string, error) { + return s.nameForType(reflect.TypeOf(i).Elem()) +} diff --git a/reflection/serverreflection_test.go b/reflection/serverreflection_test.go index 47afb1a5..94126cdc 100644 --- a/reflection/serverreflection_test.go +++ b/reflection/serverreflection_test.go @@ -2,7 +2,6 @@ package main import ( "reflect" - "sort" "testing" pb "google.golang.org/grpc/reflection/grpc_testing" @@ -13,3 +12,62 @@ var ( ) // TODO TestFileDescForType(t *testing.T) + +func TestTypeForName(t *testing.T) { + for _, test := range []struct { + name string + want reflect.Type + }{ + {"grpc.testing.SearchResponse", reflect.TypeOf(pb.SearchResponse{})}, + } { + r, err := s.typeForName(test.name) + // TODO remove all Logf + t.Logf("typeForName(%q) = %q, %v", test.name, r, err) + if err != nil || r != test.want { + t.Fatalf("typeForName(%q) = %q, %v, want %q, ", test.name, r, err, test.want) + } + } +} + +func TestTypeForNameNotFound(t *testing.T) { + for _, test := range []string{ + "grpc.testing.not_exiting", + } { + _, err := s.typeForName(test) + if err == nil { + t.Fatalf("typeForName(%q) = _, %v, want _, ", test, err) + } + } +} + +func TestNameForType(t *testing.T) { + for _, test := range []struct { + st reflect.Type + want string + }{ + {reflect.TypeOf(pb.SearchResponse{}), "grpc.testing.SearchResponse"}, + {reflect.TypeOf(pb.SearchResponse_Result{}), "grpc.testing.SearchResponse_Result"}, + } { + r, err := s.nameForType(test.st) + t.Logf("nameForType(%q) = %q, %v", test.st, r, err) + if err != nil || r != test.want { + t.Fatalf("nameForType(%q) = %q, %v, want %q, ", test.st, r, err, test.want) + } + } +} + +func TestNameForPointer(t *testing.T) { + for _, test := range []struct { + pt interface{} + want string + }{ + {&pb.SearchResponse{}, "grpc.testing.SearchResponse"}, + {&pb.SearchResponse_Result{}, "grpc.testing.SearchResponse_Result"}, + } { + r, err := s.nameForPointer(test.pt) + t.Logf("nameForPointer(%T) = %q, %v", test.pt, r, err) + if err != nil || r != test.want { + t.Fatalf("nameForPointer(%T) = %q, %v, want %q, ", test.pt, r, err, test.want) + } + } +}