blob: fc3a2eefaec0b657ea3006d0b57eadda4d7091eb [file] [log] [blame]
Joe Tsai90fe9962018-10-18 11:06:29 -07001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package impl
6
7import (
8 "reflect"
9 "testing"
10
11 "github.com/golang/protobuf/v2/internal/pragma"
12 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
13 ptype "github.com/golang/protobuf/v2/reflect/prototype"
14 "github.com/google/go-cmp/cmp"
15)
16
17func mustLoadFileDesc(b []byte) pref.FileDescriptor {
18 fd, err := ptype.NewFileFromDescriptorProto(loadFileDesc(b), nil)
19 if err != nil {
20 panic(err)
21 }
22 return fd
23}
24
25var fileDescLP2 = mustLoadFileDesc(LP2FileDescriptor)
26var fileDescLP3 = mustLoadFileDesc(LP3FileDescriptor)
27
28func TestLegacy(t *testing.T) {
29 tests := []struct {
30 got pref.Descriptor
31 want pref.Descriptor
32 }{{
33 got: loadEnumDesc(reflect.TypeOf(LP2MapEnum(0))),
34 want: fileDescLP2.Enums().ByName("LP2MapEnum"),
35 }, {
36 got: loadEnumDesc(reflect.TypeOf(LP2SiblingEnum(0))),
37 want: fileDescLP2.Enums().ByName("LP2SiblingEnum"),
38 }, {
39 got: loadEnumDesc(reflect.TypeOf(LP2Message_LP2ChildEnum(0))),
40 want: fileDescLP2.Messages().ByName("LP2Message").Enums().ByName("LP2ChildEnum"),
41 }, {
42 got: loadMessageDesc(reflect.TypeOf(new(LP2Message))),
43 want: fileDescLP2.Messages().ByName("LP2Message"),
44 }, {
45 got: loadMessageDesc(reflect.TypeOf(new(LP2Message_LP2ChildMessage))),
46 want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("LP2ChildMessage"),
47 }, {
48 got: loadMessageDesc(reflect.TypeOf(new(LP2Message_LP2NamedGroup))),
49 want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("LP2NamedGroup"),
50 }, {
51 got: loadMessageDesc(reflect.TypeOf(new(LP2Message_OptionalGroup))),
52 want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("OptionalGroup"),
53 }, {
54 got: loadMessageDesc(reflect.TypeOf(new(LP2Message_RequiredGroup))),
55 want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("RequiredGroup"),
56 }, {
57 got: loadMessageDesc(reflect.TypeOf(new(LP2Message_RepeatedGroup))),
58 want: fileDescLP2.Messages().ByName("LP2Message").Messages().ByName("RepeatedGroup"),
59 }, {
60 got: loadMessageDesc(reflect.TypeOf(new(LP2SiblingMessage))),
61 want: fileDescLP2.Messages().ByName("LP2SiblingMessage"),
62 }, {
63 got: loadEnumDesc(reflect.TypeOf(LP3SiblingEnum(0))),
64 want: fileDescLP3.Enums().ByName("LP3SiblingEnum"),
65 }, {
66 got: loadEnumDesc(reflect.TypeOf(LP3Message_LP3ChildEnum(0))),
67 want: fileDescLP3.Messages().ByName("LP3Message").Enums().ByName("LP3ChildEnum"),
68 }, {
69 got: loadMessageDesc(reflect.TypeOf(new(LP3Message))),
70 want: fileDescLP3.Messages().ByName("LP3Message"),
71 }, {
72 got: loadMessageDesc(reflect.TypeOf(new(LP3Message_LP3ChildMessage))),
73 want: fileDescLP3.Messages().ByName("LP3Message").Messages().ByName("LP3ChildMessage"),
74 }, {
75 got: loadMessageDesc(reflect.TypeOf(new(LP3SiblingMessage))),
76 want: fileDescLP3.Messages().ByName("LP3SiblingMessage"),
77 }}
78
79 type list interface {
80 Len() int
81 pragma.DoNotImplement
82 }
83 opts := cmp.Options{
84 cmp.Transformer("", func(x list) []interface{} {
85 out := make([]interface{}, x.Len())
86 v := reflect.ValueOf(x)
87 for i := 0; i < x.Len(); i++ {
88 m := v.MethodByName("Get")
89 out[i] = m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface()
90 }
91 return out
92 }),
93 cmp.Transformer("", func(x pref.Descriptor) map[string]interface{} {
94 out := make(map[string]interface{})
95 v := reflect.ValueOf(x)
96 for i := 0; i < v.NumMethod(); i++ {
97 name := v.Type().Method(i).Name
98 if m := v.Method(i); m.Type().NumIn() == 0 && m.Type().NumOut() == 1 {
99 switch name {
100 case "Index":
101 // Ignore index since legacy descriptors have no parent.
Damien Neil204f1c02018-10-23 15:03:38 -0700102 case "Options":
103 // Ignore descriptor options since protos are not cmperable.
Joe Tsai90fe9962018-10-18 11:06:29 -0700104 case "Messages", "Enums":
105 // Ignore nested message and enum declarations since
106 // legacy descriptors are all created standalone.
107 case "OneofType", "ExtendedType", "MessageType", "EnumType":
108 // Avoid descending into a dependency to avoid a cycle.
109 // Just record the full name if available.
110 //
111 // TODO: Cycle support in cmp would be useful here.
112 v := m.Call(nil)[0]
113 if !v.IsNil() {
114 out[name] = v.Interface().(pref.Descriptor).FullName()
115 }
116 default:
117 out[name] = m.Call(nil)[0].Interface()
118 }
119 }
120 }
121 return out
122 }),
123 cmp.Transformer("", func(v pref.Value) interface{} {
124 return v.Interface()
125 }),
126 }
127
128 for _, tt := range tests {
129 t.Run(string(tt.want.FullName()), func(t *testing.T) {
130 if diff := cmp.Diff(&tt.want, &tt.got, opts); diff != "" {
131 t.Errorf("descriptor mismatch (-want, +got):\n%s", diff)
132 }
133 })
134 }
135}