blob: e182d17eef663bb0b2c3752c2c7a47ee6e12122a [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.
102 case "Messages", "Enums":
103 // Ignore nested message and enum declarations since
104 // legacy descriptors are all created standalone.
105 case "OneofType", "ExtendedType", "MessageType", "EnumType":
106 // Avoid descending into a dependency to avoid a cycle.
107 // Just record the full name if available.
108 //
109 // TODO: Cycle support in cmp would be useful here.
110 v := m.Call(nil)[0]
111 if !v.IsNil() {
112 out[name] = v.Interface().(pref.Descriptor).FullName()
113 }
114 default:
115 out[name] = m.Call(nil)[0].Interface()
116 }
117 }
118 }
119 return out
120 }),
121 cmp.Transformer("", func(v pref.Value) interface{} {
122 return v.Interface()
123 }),
124 }
125
126 for _, tt := range tests {
127 t.Run(string(tt.want.FullName()), func(t *testing.T) {
128 if diff := cmp.Diff(&tt.want, &tt.got, opts); diff != "" {
129 t.Errorf("descriptor mismatch (-want, +got):\n%s", diff)
130 }
131 })
132 }
133}