// Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "testing" "github.com/golang/protobuf/v2/internal/pragma" pref "github.com/golang/protobuf/v2/reflect/protoreflect" ptype "github.com/golang/protobuf/v2/reflect/prototype" "github.com/google/go-cmp/cmp" ) func mustLoadFileDesc(b []byte) pref.FileDescriptor { fd, err := ptype.NewFileFromDescriptorProto(loadFileDesc(b), nil) if err != nil { panic(err) } return fd } var fileDescLP2 = mustLoadFileDesc(LP2FileDescriptor) var fileDescLP3 = mustLoadFileDesc(LP3FileDescriptor) func TestLegacy(t *testing.T) { tests := []struct { got pref.Descriptor want pref.Descriptor }{{ got: loadEnumDesc(reflect.TypeOf(LP2MapEnum(0))), want: fileDescLP2.Enums().ByName("LP2MapEnum"), }, { got: loadEnumDesc(reflect.TypeOf(LP2SiblingEnum(0))), want: fileDescLP2.Enums().ByName("LP2SiblingEnum"), }, { got: loadEnumDesc(reflect.TypeOf(LP2Message_LP2ChildEnum(0))), want: fileDescLP2.Messages().ByName("LP2Message").Enums().ByName("LP2ChildEnum"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2Message))), want: fileDescLP2.Messages().ByName("LP2Message"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2Message_LP2ChildMessage))), want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("LP2ChildMessage"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2Message_LP2NamedGroup))), want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("LP2NamedGroup"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2Message_OptionalGroup))), want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("OptionalGroup"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2Message_RequiredGroup))), want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("RequiredGroup"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2Message_RepeatedGroup))), want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("RepeatedGroup"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP2SiblingMessage))), want: fileDescLP2.Messages().ByName("LP2SiblingMessage"), }, { got: loadEnumDesc(reflect.TypeOf(LP3SiblingEnum(0))), want: fileDescLP3.Enums().ByName("LP3SiblingEnum"), }, { got: loadEnumDesc(reflect.TypeOf(LP3Message_LP3ChildEnum(0))), want: fileDescLP3.Messages().ByName("LP3Message").Enums().ByName("LP3ChildEnum"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP3Message))), want: fileDescLP3.Messages().ByName("LP3Message"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP3Message_LP3ChildMessage))), want: fileDescLP3.Messages().ByName("LP3Message").Messages().ByName("LP3ChildMessage"), }, { got: loadMessageDesc(reflect.TypeOf(new(LP3SiblingMessage))), want: fileDescLP3.Messages().ByName("LP3SiblingMessage"), }} type list interface { Len() int pragma.DoNotImplement } opts := cmp.Options{ cmp.Transformer("", func(x list) []interface{} { out := make([]interface{}, x.Len()) v := reflect.ValueOf(x) for i := 0; i < x.Len(); i++ { m := v.MethodByName("Get") out[i] = m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface() } return out }), cmp.Transformer("", func(x pref.Descriptor) map[string]interface{} { out := make(map[string]interface{}) v := reflect.ValueOf(x) for i := 0; i < v.NumMethod(); i++ { name := v.Type().Method(i).Name if m := v.Method(i); m.Type().NumIn() == 0 && m.Type().NumOut() == 1 { switch name { case "Index": // Ignore index since legacy descriptors have no parent. case "Options": // Ignore descriptor options since protos are not cmperable. case "Messages", "Enums": // Ignore nested message and enum declarations since // legacy descriptors are all created standalone. case "OneofType", "ExtendedType", "MessageType", "EnumType": // Avoid descending into a dependency to avoid a cycle. // Just record the full name if available. // // TODO: Cycle support in cmp would be useful here. v := m.Call(nil)[0] if !v.IsNil() { out[name] = v.Interface().(pref.Descriptor).FullName() } default: out[name] = m.Call(nil)[0].Interface() } } } return out }), cmp.Transformer("", func(v pref.Value) interface{} { return v.Interface() }), } for _, tt := range tests { t.Run(string(tt.want.FullName()), func(t *testing.T) { if diff := cmp.Diff(&tt.want, &tt.got, opts); diff != "" { t.Errorf("descriptor mismatch (-want, +got):\n%s", diff) } }) } }