Source file
src/reflect/visiblefields_test.go
Documentation: reflect
1
2
3
4
5 package reflect_test
6
7 import (
8 . "reflect"
9 "testing"
10 )
11
12 type structField struct {
13 name string
14 index []int
15 }
16
17 var fieldsTests = []struct {
18 testName string
19 val interface{}
20 expect []structField
21 }{{
22 testName: "SimpleStruct",
23 val: struct {
24 A int
25 B string
26 C bool
27 }{},
28 expect: []structField{{
29 name: "A",
30 index: []int{0},
31 }, {
32 name: "B",
33 index: []int{1},
34 }, {
35 name: "C",
36 index: []int{2},
37 }},
38 }, {
39 testName: "NonEmbeddedStructMember",
40 val: struct {
41 A struct {
42 X int
43 }
44 }{},
45 expect: []structField{{
46 name: "A",
47 index: []int{0},
48 }},
49 }, {
50 testName: "EmbeddedExportedStruct",
51 val: struct {
52 SFG
53 }{},
54 expect: []structField{{
55 name: "SFG",
56 index: []int{0},
57 }, {
58 name: "F",
59 index: []int{0, 0},
60 }, {
61 name: "G",
62 index: []int{0, 1},
63 }},
64 }, {
65 testName: "EmbeddedUnexportedStruct",
66 val: struct {
67 sFG
68 }{},
69 expect: []structField{{
70 name: "sFG",
71 index: []int{0},
72 }, {
73 name: "F",
74 index: []int{0, 0},
75 }, {
76 name: "G",
77 index: []int{0, 1},
78 }},
79 }, {
80 testName: "TwoEmbeddedStructsWithCancellingMembers",
81 val: struct {
82 SFG
83 SF
84 }{},
85 expect: []structField{{
86 name: "SFG",
87 index: []int{0},
88 }, {
89 name: "G",
90 index: []int{0, 1},
91 }, {
92 name: "SF",
93 index: []int{1},
94 }},
95 }, {
96 testName: "EmbeddedStructsWithSameFieldsAtDifferentDepths",
97 val: struct {
98 SFGH3
99 SG1
100 SFG2
101 SF2
102 L int
103 }{},
104 expect: []structField{{
105 name: "SFGH3",
106 index: []int{0},
107 }, {
108 name: "SFGH2",
109 index: []int{0, 0},
110 }, {
111 name: "SFGH1",
112 index: []int{0, 0, 0},
113 }, {
114 name: "SFGH",
115 index: []int{0, 0, 0, 0},
116 }, {
117 name: "H",
118 index: []int{0, 0, 0, 0, 2},
119 }, {
120 name: "SG1",
121 index: []int{1},
122 }, {
123 name: "SG",
124 index: []int{1, 0},
125 }, {
126 name: "G",
127 index: []int{1, 0, 0},
128 }, {
129 name: "SFG2",
130 index: []int{2},
131 }, {
132 name: "SFG1",
133 index: []int{2, 0},
134 }, {
135 name: "SFG",
136 index: []int{2, 0, 0},
137 }, {
138 name: "SF2",
139 index: []int{3},
140 }, {
141 name: "SF1",
142 index: []int{3, 0},
143 }, {
144 name: "SF",
145 index: []int{3, 0, 0},
146 }, {
147 name: "L",
148 index: []int{4},
149 }},
150 }, {
151 testName: "EmbeddedPointerStruct",
152 val: struct {
153 *SF
154 }{},
155 expect: []structField{{
156 name: "SF",
157 index: []int{0},
158 }, {
159 name: "F",
160 index: []int{0, 0},
161 }},
162 }, {
163 testName: "EmbeddedNotAPointer",
164 val: struct {
165 M
166 }{},
167 expect: []structField{{
168 name: "M",
169 index: []int{0},
170 }},
171 }, {
172 testName: "RecursiveEmbedding",
173 val: Rec1{},
174 expect: []structField{{
175 name: "Rec2",
176 index: []int{0},
177 }, {
178 name: "F",
179 index: []int{0, 0},
180 }, {
181 name: "Rec1",
182 index: []int{0, 1},
183 }},
184 }, {
185 testName: "RecursiveEmbedding2",
186 val: Rec2{},
187 expect: []structField{{
188 name: "F",
189 index: []int{0},
190 }, {
191 name: "Rec1",
192 index: []int{1},
193 }, {
194 name: "Rec2",
195 index: []int{1, 0},
196 }},
197 }, {
198 testName: "RecursiveEmbedding3",
199 val: RS3{},
200 expect: []structField{{
201 name: "RS2",
202 index: []int{0},
203 }, {
204 name: "RS1",
205 index: []int{1},
206 }, {
207 name: "i",
208 index: []int{1, 0},
209 }},
210 }}
211
212 type SFG struct {
213 F int
214 G int
215 }
216
217 type SFG1 struct {
218 SFG
219 }
220
221 type SFG2 struct {
222 SFG1
223 }
224
225 type SFGH struct {
226 F int
227 G int
228 H int
229 }
230
231 type SFGH1 struct {
232 SFGH
233 }
234
235 type SFGH2 struct {
236 SFGH1
237 }
238
239 type SFGH3 struct {
240 SFGH2
241 }
242
243 type SF struct {
244 F int
245 }
246
247 type SF1 struct {
248 SF
249 }
250
251 type SF2 struct {
252 SF1
253 }
254
255 type SG struct {
256 G int
257 }
258
259 type SG1 struct {
260 SG
261 }
262
263 type sFG struct {
264 F int
265 G int
266 }
267
268 type RS1 struct {
269 i int
270 }
271
272 type RS2 struct {
273 RS1
274 }
275
276 type RS3 struct {
277 RS2
278 RS1
279 }
280
281 type M map[string]interface{}
282
283 type Rec1 struct {
284 *Rec2
285 }
286
287 type Rec2 struct {
288 F string
289 *Rec1
290 }
291
292 func TestFields(t *testing.T) {
293 for _, test := range fieldsTests {
294 test := test
295 t.Run(test.testName, func(t *testing.T) {
296 typ := TypeOf(test.val)
297 fields := VisibleFields(typ)
298 if got, want := len(fields), len(test.expect); got != want {
299 t.Fatalf("unexpected field count; got %d want %d", got, want)
300 }
301
302 for j, field := range fields {
303 expect := test.expect[j]
304 t.Logf("field %d: %s", j, expect.name)
305 gotField := typ.FieldByIndex(field.Index)
306
307
308
309
310 gotField.Index = field.Index
311 expectField := typ.FieldByIndex(expect.index)
312
313 expectField.Index = expect.index
314 if !DeepEqual(gotField, expectField) {
315 t.Fatalf("unexpected field result\ngot %#v\nwant %#v", gotField, expectField)
316 }
317
318
319
320 gotField1, ok := typ.FieldByName(expect.name)
321 if !ok {
322 t.Fatalf("field %q not accessible by name", expect.name)
323 }
324 if !DeepEqual(gotField1, expectField) {
325 t.Fatalf("unexpected FieldByName result; got %#v want %#v", gotField1, expectField)
326 }
327 }
328 })
329 }
330 }
331
View as plain text