c++: decltype of (by-value captured reference) [PR79620]
[official-gcc.git] / libgo / go / reflect / visiblefields_test.go
blobfdedc21f738b57ab830ec91ea84418eaa4a371a9
1 // Copyright 2021 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.
5 package reflect_test
7 import (
8 . "reflect"
9 "strings"
10 "testing"
13 type structField struct {
14 name string
15 index []int
18 var fieldsTests = []struct {
19 testName string
20 val any
21 expect []structField
22 }{{
23 testName: "SimpleStruct",
24 val: struct {
25 A int
26 B string
27 C bool
28 }{},
29 expect: []structField{{
30 name: "A",
31 index: []int{0},
32 }, {
33 name: "B",
34 index: []int{1},
35 }, {
36 name: "C",
37 index: []int{2},
38 }},
39 }, {
40 testName: "NonEmbeddedStructMember",
41 val: struct {
42 A struct {
43 X int
45 }{},
46 expect: []structField{{
47 name: "A",
48 index: []int{0},
49 }},
50 }, {
51 testName: "EmbeddedExportedStruct",
52 val: struct {
53 SFG
54 }{},
55 expect: []structField{{
56 name: "SFG",
57 index: []int{0},
58 }, {
59 name: "F",
60 index: []int{0, 0},
61 }, {
62 name: "G",
63 index: []int{0, 1},
64 }},
65 }, {
66 testName: "EmbeddedUnexportedStruct",
67 val: struct {
68 sFG
69 }{},
70 expect: []structField{{
71 name: "sFG",
72 index: []int{0},
73 }, {
74 name: "F",
75 index: []int{0, 0},
76 }, {
77 name: "G",
78 index: []int{0, 1},
79 }},
80 }, {
81 testName: "TwoEmbeddedStructsWithCancellingMembers",
82 val: struct {
83 SFG
85 }{},
86 expect: []structField{{
87 name: "SFG",
88 index: []int{0},
89 }, {
90 name: "G",
91 index: []int{0, 1},
92 }, {
93 name: "SF",
94 index: []int{1},
95 }},
96 }, {
97 testName: "EmbeddedStructsWithSameFieldsAtDifferentDepths",
98 val: struct {
99 SFGH3
101 SFG2
103 L int
104 }{},
105 expect: []structField{{
106 name: "SFGH3",
107 index: []int{0},
108 }, {
109 name: "SFGH2",
110 index: []int{0, 0},
111 }, {
112 name: "SFGH1",
113 index: []int{0, 0, 0},
114 }, {
115 name: "SFGH",
116 index: []int{0, 0, 0, 0},
117 }, {
118 name: "H",
119 index: []int{0, 0, 0, 0, 2},
120 }, {
121 name: "SG1",
122 index: []int{1},
123 }, {
124 name: "SG",
125 index: []int{1, 0},
126 }, {
127 name: "G",
128 index: []int{1, 0, 0},
129 }, {
130 name: "SFG2",
131 index: []int{2},
132 }, {
133 name: "SFG1",
134 index: []int{2, 0},
135 }, {
136 name: "SFG",
137 index: []int{2, 0, 0},
138 }, {
139 name: "SF2",
140 index: []int{3},
141 }, {
142 name: "SF1",
143 index: []int{3, 0},
144 }, {
145 name: "SF",
146 index: []int{3, 0, 0},
147 }, {
148 name: "L",
149 index: []int{4},
151 }, {
152 testName: "EmbeddedPointerStruct",
153 val: struct {
155 }{},
156 expect: []structField{{
157 name: "SF",
158 index: []int{0},
159 }, {
160 name: "F",
161 index: []int{0, 0},
163 }, {
164 testName: "EmbeddedNotAPointer",
165 val: struct {
167 }{},
168 expect: []structField{{
169 name: "M",
170 index: []int{0},
172 }, {
173 testName: "RecursiveEmbedding",
174 val: Rec1{},
175 expect: []structField{{
176 name: "Rec2",
177 index: []int{0},
178 }, {
179 name: "F",
180 index: []int{0, 0},
181 }, {
182 name: "Rec1",
183 index: []int{0, 1},
185 }, {
186 testName: "RecursiveEmbedding2",
187 val: Rec2{},
188 expect: []structField{{
189 name: "F",
190 index: []int{0},
191 }, {
192 name: "Rec1",
193 index: []int{1},
194 }, {
195 name: "Rec2",
196 index: []int{1, 0},
198 }, {
199 testName: "RecursiveEmbedding3",
200 val: RS3{},
201 expect: []structField{{
202 name: "RS2",
203 index: []int{0},
204 }, {
205 name: "RS1",
206 index: []int{1},
207 }, {
208 name: "i",
209 index: []int{1, 0},
213 type SFG struct {
214 F int
215 G int
218 type SFG1 struct {
222 type SFG2 struct {
223 SFG1
226 type SFGH struct {
227 F int
228 G int
229 H int
232 type SFGH1 struct {
233 SFGH
236 type SFGH2 struct {
237 SFGH1
240 type SFGH3 struct {
241 SFGH2
244 type SF struct {
245 F int
248 type SF1 struct {
252 type SF2 struct {
256 type SG struct {
257 G int
260 type SG1 struct {
264 type sFG struct {
265 F int
266 G int
269 type RS1 struct {
270 i int
273 type RS2 struct {
277 type RS3 struct {
282 type M map[string]any
284 type Rec1 struct {
285 *Rec2
288 type Rec2 struct {
289 F string
290 *Rec1
293 func TestFields(t *testing.T) {
294 for _, test := range fieldsTests {
295 test := test
296 t.Run(test.testName, func(t *testing.T) {
297 typ := TypeOf(test.val)
298 fields := VisibleFields(typ)
299 if got, want := len(fields), len(test.expect); got != want {
300 t.Fatalf("unexpected field count; got %d want %d", got, want)
303 for j, field := range fields {
304 expect := test.expect[j]
305 t.Logf("field %d: %s", j, expect.name)
306 gotField := typ.FieldByIndex(field.Index)
307 // Unfortunately, FieldByIndex does not return
308 // a field with the same index that we passed in,
309 // so we set it to the expected value so that
310 // it can be compared later with the result of FieldByName.
311 gotField.Index = field.Index
312 expectField := typ.FieldByIndex(expect.index)
313 // ditto.
314 expectField.Index = expect.index
315 if !DeepEqual(gotField, expectField) {
316 t.Fatalf("unexpected field result\ngot %#v\nwant %#v", gotField, expectField)
319 // Sanity check that we can actually access the field by the
320 // expected name.
321 gotField1, ok := typ.FieldByName(expect.name)
322 if !ok {
323 t.Fatalf("field %q not accessible by name", expect.name)
325 if !DeepEqual(gotField1, expectField) {
326 t.Fatalf("unexpected FieldByName result; got %#v want %#v", gotField1, expectField)
333 // Must not panic with nil embedded pointer.
334 func TestFieldByIndexErr(t *testing.T) {
335 type A struct {
336 S string
338 type B struct {
341 v := ValueOf(B{})
342 _, err := v.FieldByIndexErr([]int{0, 0})
343 if err == nil {
344 t.Fatal("expected error")
346 if !strings.Contains(err.Error(), "embedded struct field A") {
347 t.Fatal(err)