istio

Форк
0
/
reflect_test.go 
413 строк · 10.2 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package util
16

17
import (
18
	"reflect"
19
	"testing"
20
)
21

22
// TODO: add missing unit tests (istio/istio#17246).
23

24
// errToString returns the string representation of err and the empty string if
25
// err is nil.
26
func errToString(err error) string {
27
	if err == nil {
28
		return ""
29
	}
30
	return err.Error()
31
}
32

33
// to ptr conversion utility functions
34
func toInt8Ptr(i int8) *int8 { return &i }
35

36
func TestIsValueNil(t *testing.T) {
37
	if !IsValueNil(nil) {
38
		t.Error("got IsValueNil(nil) false, want true")
39
	}
40
	if !IsValueNil((*int)(nil)) {
41
		t.Error("got IsValueNil(ptr) false, want true")
42
	}
43
	if !IsValueNil(map[int]int(nil)) {
44
		t.Error("got IsValueNil(map) false, want true")
45
	}
46
	if !IsValueNil([]int(nil)) {
47
		t.Error("got IsValueNil(slice) false, want true")
48
	}
49
	if !IsValueNil(any(nil)) {
50
		t.Error("got IsValueNil(interface) false, want true")
51
	}
52

53
	if IsValueNil(toInt8Ptr(42)) {
54
		t.Error("got IsValueNil(ptr) true, want false")
55
	}
56
	if IsValueNil(map[int]int{42: 42}) {
57
		t.Error("got IsValueNil(map) true, want false")
58
	}
59
	if IsValueNil([]int{1, 2, 3}) {
60
		t.Error("got IsValueNil(slice) true, want false")
61
	}
62
	if IsValueNil(any(42)) {
63
		t.Error("got IsValueNil(interface) true, want false")
64
	}
65
}
66

67
func TestIsValueNilOrDefault(t *testing.T) {
68
	if !IsValueNilOrDefault(nil) {
69
		t.Error("got IsValueNilOrDefault(nil) false, want true")
70
	}
71
	if !IsValueNilOrDefault((*int)(nil)) {
72
		t.Error("got IsValueNilOrDefault(ptr) false, want true")
73
	}
74
	if !IsValueNilOrDefault(map[int]int(nil)) {
75
		t.Error("got IsValueNilOrDefault(map) false, want true")
76
	}
77
	if !IsValueNilOrDefault([]int(nil)) {
78
		t.Error("got IsValueNilOrDefault(slice) false, want true")
79
	}
80
	if !IsValueNilOrDefault(any(nil)) {
81
		t.Error("got IsValueNilOrDefault(interface) false, want true")
82
	}
83
	if !IsValueNilOrDefault(int(0)) {
84
		t.Error("got IsValueNilOrDefault(int(0)) false, want true")
85
	}
86
	if !IsValueNilOrDefault("") {
87
		t.Error("got IsValueNilOrDefault(\"\") false, want true")
88
	}
89
	if !IsValueNilOrDefault(false) {
90
		t.Error("got IsValueNilOrDefault(false) false, want true")
91
	}
92
	i := 32
93
	ip := &i
94
	if IsValueNilOrDefault(&ip) {
95
		t.Error("got IsValueNilOrDefault(ptr to ptr) false, want true")
96
	}
97
}
98

99
func TestIsValueFuncs(t *testing.T) {
100
	testInt := int(42)
101
	testStruct := struct{}{}
102
	testSlice := []bool{}
103
	testMap := map[bool]bool{}
104
	var testNilSlice []bool
105
	var testNilMap map[bool]bool
106

107
	allValues := []any{nil, testInt, &testInt, testStruct, &testStruct, testNilSlice, testSlice, &testSlice, testNilMap, testMap, &testMap}
108

109
	tests := []struct {
110
		desc     string
111
		function func(v reflect.Value) bool
112
		okValues []any
113
	}{
114
		{
115
			desc:     "IsValuePtr",
116
			function: IsValuePtr,
117
			okValues: []any{&testInt, &testStruct, &testSlice, &testMap},
118
		},
119
		{
120
			desc:     "IsValueStruct",
121
			function: IsValueStruct,
122
			okValues: []any{testStruct},
123
		},
124
		{
125
			desc:     "IsValueInterface",
126
			function: IsValueInterface,
127
			okValues: []any{},
128
		},
129
		{
130
			desc:     "IsValueStructPtr",
131
			function: IsValueStructPtr,
132
			okValues: []any{&testStruct},
133
		},
134
		{
135
			desc:     "IsValueMap",
136
			function: IsValueMap,
137
			okValues: []any{testNilMap, testMap},
138
		},
139
		{
140
			desc:     "IsValueSlice",
141
			function: IsValueSlice,
142
			okValues: []any{testNilSlice, testSlice},
143
		},
144
		{
145
			desc:     "IsValueScalar",
146
			function: IsValueScalar,
147
			okValues: []any{testInt, &testInt},
148
		},
149
	}
150

151
	for _, tt := range tests {
152
		for vidx, v := range allValues {
153
			if got, want := tt.function(reflect.ValueOf(v)), isInListOfInterface(tt.okValues, v); got != want {
154
				t.Errorf("%s with %s (#%d): got: %t, want: %t", tt.desc, reflect.TypeOf(v), vidx, got, want)
155
			}
156
		}
157
	}
158
}
159

160
func TestValuesAreSameType(t *testing.T) {
161
	type EnumType int64
162

163
	tests := []struct {
164
		inDesc string
165
		inV1   any
166
		inV2   any
167
		want   bool
168
	}{
169
		{
170
			inDesc: "success both are int32 types",
171
			inV1:   int32(42),
172
			inV2:   int32(43),
173
			want:   true,
174
		},
175
		{
176
			inDesc: "fail unmatching int types",
177
			inV1:   int16(42),
178
			inV2:   int32(43),
179
			want:   false,
180
		},
181
		{
182
			inDesc: "fail unmatching int and string type",
183
			inV1:   int32(42),
184
			inV2:   "42",
185
			want:   false,
186
		},
187
		{
188
			inDesc: "fail EnumType and int64 types",
189
			inV1:   EnumType(42),
190
			inV2:   int64(43),
191
			want:   false,
192
		},
193
	}
194

195
	for _, tt := range tests {
196
		t.Run(tt.inDesc, func(t *testing.T) {
197
			got := ValuesAreSameType(reflect.ValueOf(tt.inV1), reflect.ValueOf(tt.inV2))
198
			if got != tt.want {
199
				t.Errorf("got %v, want %v for comparing %T against %T", got, tt.want, tt.inV1, tt.inV2)
200
			}
201
		})
202
	}
203
}
204

205
func TestIsTypeFuncs(t *testing.T) {
206
	testInt := int(42)
207
	testStruct := struct{}{}
208
	testSlice := []bool{}
209
	testSliceOfInterface := []any{}
210
	testMap := map[bool]bool{}
211
	var testNilSlice []bool
212
	var testNilMap map[bool]bool
213

214
	allTypes := []any{
215
		nil, testInt, &testInt, testStruct, &testStruct, testNilSlice,
216
		testSlice, &testSlice, testSliceOfInterface, testNilMap, testMap, &testMap,
217
	}
218

219
	tests := []struct {
220
		desc     string
221
		function func(v reflect.Type) bool
222
		okTypes  []any
223
	}{
224
		{
225
			desc:     "IsTypeStructPtr",
226
			function: IsTypeStructPtr,
227
			okTypes:  []any{&testStruct},
228
		},
229
		{
230
			desc:     "IsTypeSlicePtr",
231
			function: IsTypeSlicePtr,
232
			okTypes:  []any{&testSlice},
233
		},
234
		{
235
			desc:     "IsTypeMap",
236
			function: IsTypeMap,
237
			okTypes:  []any{testNilMap, testMap},
238
		},
239
		{
240
			desc:     "IsTypeInterface",
241
			function: IsTypeInterface,
242
			okTypes:  []any{},
243
		},
244
		{
245
			desc:     "IsTypeSliceOfInterface",
246
			function: IsTypeSliceOfInterface,
247
			okTypes:  []any{testSliceOfInterface},
248
		},
249
	}
250

251
	for _, tt := range tests {
252
		for vidx, v := range allTypes {
253
			if got, want := tt.function(reflect.TypeOf(v)), isInListOfInterface(tt.okTypes, v); got != want {
254
				t.Errorf("%s with %s (#%d): got: %t, want: %t", tt.desc, reflect.TypeOf(v), vidx, got, want)
255
			}
256
		}
257
	}
258
}
259

260
type interfaceContainer struct {
261
	I anInterface
262
}
263

264
type anInterface interface {
265
	IsU()
266
}
267

268
type implementsInterface struct {
269
	A string
270
}
271

272
func (*implementsInterface) IsU() {}
273

274
func TestIsValueInterface(t *testing.T) {
275
	intf := &interfaceContainer{
276
		I: &implementsInterface{
277
			A: "a",
278
		},
279
	}
280
	iField := reflect.ValueOf(intf).Elem().FieldByName("I")
281
	if !IsValueInterface(iField) {
282
		t.Errorf("IsValueInterface(): got false, want true")
283
	}
284
}
285

286
func TestIsTypeInterface(t *testing.T) {
287
	intf := &interfaceContainer{
288
		I: &implementsInterface{
289
			A: "a",
290
		},
291
	}
292
	testIfField := reflect.ValueOf(intf).Elem().Field(0)
293

294
	if !IsTypeInterface(testIfField.Type()) {
295
		t.Errorf("IsTypeInterface(): got false, want true")
296
	}
297
}
298

299
func isInListOfInterface(lv []any, v any) bool {
300
	for _, vv := range lv {
301
		if reflect.DeepEqual(vv, v) {
302
			return true
303
		}
304
	}
305
	return false
306
}
307

308
func TestDeleteFromSlicePtr(t *testing.T) {
309
	parentSlice := []int{42, 43, 44, 45}
310
	var parentSliceI any = parentSlice
311
	if err := DeleteFromSlicePtr(&parentSliceI, 1); err != nil {
312
		t.Fatalf("got error: %s, want error: nil", err)
313
	}
314
	wantSlice := []int{42, 44, 45}
315
	if got, want := parentSliceI, wantSlice; !reflect.DeepEqual(got, want) {
316
		t.Errorf("got:\n%v\nwant:\n%v\n", got, want)
317
	}
318

319
	badParent := struct{}{}
320
	wantErr := `deleteFromSlicePtr parent type is *struct {}, must be *[]interface{}`
321
	if got, want := errToString(DeleteFromSlicePtr(&badParent, 1)), wantErr; got != want {
322
		t.Fatalf("got error: %s, want error: %s", got, want)
323
	}
324
}
325

326
func TestUpdateSlicePtr(t *testing.T) {
327
	parentSlice := []int{42, 43, 44, 45}
328
	var parentSliceI any = parentSlice
329
	if err := UpdateSlicePtr(&parentSliceI, 1, 42); err != nil {
330
		t.Fatalf("got error: %s, want error: nil", err)
331
	}
332
	wantSlice := []int{42, 42, 44, 45}
333
	if got, want := parentSliceI, wantSlice; !reflect.DeepEqual(got, want) {
334
		t.Errorf("got:\n%v\nwant:\n%v\n", got, want)
335
	}
336

337
	badParent := struct{}{}
338
	wantErr := `updateSlicePtr parent type is *struct {}, must be *[]interface{}`
339
	if got, want := errToString(UpdateSlicePtr(&badParent, 1, 42)), wantErr; got != want {
340
		t.Fatalf("got error: %s, want error: %s", got, want)
341
	}
342
}
343

344
func TestInsertIntoMap(t *testing.T) {
345
	parentMap := map[int]string{42: "forty two", 43: "forty three"}
346
	key := 44
347
	value := "forty four"
348
	if err := InsertIntoMap(parentMap, key, value); err != nil {
349
		t.Fatalf("got error: %s, want error: nil", err)
350
	}
351
	wantMap := map[int]string{42: "forty two", 43: "forty three", 44: "forty four"}
352
	if got, want := parentMap, wantMap; !reflect.DeepEqual(got, want) {
353
		t.Errorf("got:\n%v\nwant:\n%v\n", got, want)
354
	}
355

356
	badParent := struct{}{}
357
	wantErr := `insertIntoMap parent type is *struct {}, must be map`
358
	if got, want := errToString(InsertIntoMap(&badParent, key, value)), wantErr; got != want {
359
		t.Fatalf("got error: %s, want error: %s", got, want)
360
	}
361
}
362

363
var (
364
	allIntTypes     = []any{int(-42), int8(-43), int16(-44), int32(-45), int64(-46)}
365
	allUintTypes    = []any{uint(42), uint8(43), uint16(44), uint32(45), uint64(46)}
366
	allIntegerTypes = append(allIntTypes, allUintTypes...)
367
	nonIntTypes     = []any{nil, "", []int{}, map[string]bool{}}
368
	allTypes        = append(allIntegerTypes, nonIntTypes...)
369
)
370

371
func TestIsInteger(t *testing.T) {
372
	tests := []struct {
373
		desc     string
374
		function func(v reflect.Kind) bool
375
		want     []any
376
	}{
377
		{
378
			desc:     "ints",
379
			function: IsIntKind,
380
			want:     allIntTypes,
381
		},
382
		{
383
			desc:     "uints",
384
			function: IsUintKind,
385
			want:     allUintTypes,
386
		},
387
	}
388

389
	for _, tt := range tests {
390
		var got []any
391
		for _, v := range allTypes {
392
			if tt.function(reflect.ValueOf(v).Kind()) {
393
				got = append(got, v)
394
			}
395
		}
396
		if !reflect.DeepEqual(got, tt.want) {
397
			t.Errorf("%s: got %v, want %v", tt.desc, got, tt.want)
398
		}
399
	}
400
}
401

402
func TestToIntValue(t *testing.T) {
403
	var got []int
404
	for _, v := range allTypes {
405
		if i, ok := ToIntValue(v); ok {
406
			got = append(got, i)
407
		}
408
	}
409
	want := []int{-42, -43, -44, -45, -46, 42, 43, 44, 45, 46}
410
	if !reflect.DeepEqual(got, want) {
411
		t.Errorf("got %v, want %v", got, want)
412
	}
413
}
414

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.