1
2
3
4
5 package order
6
7 import (
8 "math/rand"
9 "sort"
10 "testing"
11
12 "github.com/google/go-cmp/cmp"
13 "google.golang.org/protobuf/reflect/protoreflect"
14 )
15
16 type fieldDesc struct {
17 index int
18 name protoreflect.FullName
19 number protoreflect.FieldNumber
20 extension bool
21 oneofIndex int
22 protoreflect.FieldDescriptor
23 }
24
25 func (d fieldDesc) Index() int { return d.index }
26 func (d fieldDesc) Name() protoreflect.Name { return d.name.Name() }
27 func (d fieldDesc) FullName() protoreflect.FullName { return d.name }
28 func (d fieldDesc) Number() protoreflect.FieldNumber { return d.number }
29 func (d fieldDesc) IsExtension() bool { return d.extension }
30 func (d fieldDesc) ContainingOneof() protoreflect.OneofDescriptor {
31 switch {
32 case d.oneofIndex < 0:
33 return oneofDesc{index: -d.oneofIndex, synthetic: true}
34 case d.oneofIndex > 0:
35 return oneofDesc{index: +d.oneofIndex, synthetic: false}
36 default:
37 return nil
38 }
39 }
40
41 type oneofDesc struct {
42 index int
43 synthetic bool
44 protoreflect.OneofDescriptor
45 }
46
47 func (d oneofDesc) Index() int { return d.index }
48 func (d oneofDesc) IsSynthetic() bool { return d.synthetic }
49
50 func TestFieldOrder(t *testing.T) {
51 tests := []struct {
52 label string
53 order FieldOrder
54 fields []fieldDesc
55 }{{
56 label: "LegacyFieldOrder",
57 order: LegacyFieldOrder,
58 fields: []fieldDesc{
59
60 {number: 2, extension: true},
61 {number: 4, extension: true},
62 {number: 100, extension: true},
63 {number: 120, extension: true},
64
65
66
67 {number: 1},
68 {number: 5, oneofIndex: -10},
69 {number: 10},
70 {number: 11, oneofIndex: -9},
71 {number: 12},
72
73
74 {number: 13, oneofIndex: 4},
75 {number: 3, oneofIndex: 5},
76 {number: 9, oneofIndex: 5},
77 {number: 7, oneofIndex: 8},
78 },
79 }, {
80 label: "NumberFieldOrder",
81 order: NumberFieldOrder,
82 fields: []fieldDesc{
83 {number: 1, index: 5, name: "c"},
84 {number: 2, index: 2, name: "b"},
85 {number: 3, index: 3, name: "d"},
86 {number: 5, index: 1, name: "a"},
87 {number: 7, index: 7, name: "e"},
88 },
89 }, {
90 label: "IndexNameFieldOrder",
91 order: IndexNameFieldOrder,
92 fields: []fieldDesc{
93
94 {index: 0, number: 5, name: "c"},
95 {index: 2, number: 2, name: "a"},
96 {index: 4, number: 4, name: "b"},
97 {index: 7, number: 6, name: "d"},
98
99
100 {index: 3, number: 1, name: "d.a", extension: true},
101 {index: 5, number: 3, name: "e", extension: true},
102 {index: 1, number: 7, name: "g", extension: true},
103 },
104 }}
105
106 for _, tt := range tests {
107 t.Run(tt.label, func(t *testing.T) {
108 want := tt.fields
109 got := append([]fieldDesc(nil), want...)
110 for i, j := range rand.Perm(len(got)) {
111 got[i], got[j] = got[j], got[i]
112 }
113 sort.Slice(got, func(i, j int) bool {
114 return tt.order(got[i], got[j])
115 })
116 if diff := cmp.Diff(want, got,
117 cmp.Comparer(func(x, y fieldDesc) bool { return x == y }),
118 ); diff != "" {
119 t.Errorf("order mismatch (-want +got):\n%s", diff)
120 }
121 })
122 }
123 }
124
125 func TestKeyOrder(t *testing.T) {
126 tests := []struct {
127 label string
128 order KeyOrder
129 keys []interface{}
130 }{{
131 label: "GenericKeyOrder",
132 order: GenericKeyOrder,
133 keys: []interface{}{false, true},
134 }, {
135 label: "GenericKeyOrder",
136 order: GenericKeyOrder,
137 keys: []interface{}{int32(-100), int32(-99), int32(-10), int32(-9), int32(-1), int32(0), int32(+1), int32(+9), int32(+10), int32(+99), int32(+100)},
138 }, {
139 label: "GenericKeyOrder",
140 order: GenericKeyOrder,
141 keys: []interface{}{int64(-100), int64(-99), int64(-10), int64(-9), int64(-1), int64(0), int64(+1), int64(+9), int64(+10), int64(+99), int64(+100)},
142 }, {
143 label: "GenericKeyOrder",
144 order: GenericKeyOrder,
145 keys: []interface{}{uint32(0), uint32(1), uint32(9), uint32(10), uint32(99), uint32(100)},
146 }, {
147 label: "GenericKeyOrder",
148 order: GenericKeyOrder,
149 keys: []interface{}{uint64(0), uint64(1), uint64(9), uint64(10), uint64(99), uint64(100)},
150 }, {
151 label: "GenericKeyOrder",
152 order: GenericKeyOrder,
153 keys: []interface{}{"", "a", "aa", "ab", "ba", "bb", "\u0080", "\u0080\u0081", "\u0082\u0080"},
154 }}
155
156 for _, tt := range tests {
157 t.Run(tt.label, func(t *testing.T) {
158 var got, want []protoreflect.MapKey
159 for _, v := range tt.keys {
160 want = append(want, protoreflect.ValueOf(v).MapKey())
161 }
162 got = append(got, want...)
163 for i, j := range rand.Perm(len(got)) {
164 got[i], got[j] = got[j], got[i]
165 }
166 sort.Slice(got, func(i, j int) bool {
167 return tt.order(got[i], got[j])
168 })
169 if diff := cmp.Diff(want, got, cmp.Transformer("", protoreflect.MapKey.Interface)); diff != "" {
170 t.Errorf("order mismatch (-want +got):\n%s", diff)
171 }
172 })
173 }
174 }
175
View as plain text