1// Copyright 2009 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 reflectlite_test
6
7import (
8	"encoding/base64"
9	"fmt"
10	. "internal/reflectlite"
11	"math"
12	"reflect"
13	"runtime"
14	"testing"
15	"unsafe"
16)
17
18func ToValue(v Value) reflect.Value {
19	return reflect.ValueOf(ToInterface(v))
20}
21
22func TypeString(t Type) string {
23	return fmt.Sprintf("%T", ToInterface(Zero(t)))
24}
25
26type integer int
27type T struct {
28	a int
29	b float64
30	c string
31	d *int
32}
33
34type pair struct {
35	i any
36	s string
37}
38
39func assert(t *testing.T, s, want string) {
40	t.Helper()
41	if s != want {
42		t.Errorf("have %#q want %#q", s, want)
43	}
44}
45
46var typeTests = []pair{
47	{struct{ x int }{}, "int"},
48	{struct{ x int8 }{}, "int8"},
49	{struct{ x int16 }{}, "int16"},
50	{struct{ x int32 }{}, "int32"},
51	{struct{ x int64 }{}, "int64"},
52	{struct{ x uint }{}, "uint"},
53	{struct{ x uint8 }{}, "uint8"},
54	{struct{ x uint16 }{}, "uint16"},
55	{struct{ x uint32 }{}, "uint32"},
56	{struct{ x uint64 }{}, "uint64"},
57	{struct{ x float32 }{}, "float32"},
58	{struct{ x float64 }{}, "float64"},
59	{struct{ x int8 }{}, "int8"},
60	{struct{ x (**int8) }{}, "**int8"},
61	{struct{ x (**integer) }{}, "**reflectlite_test.integer"},
62	{struct{ x ([32]int32) }{}, "[32]int32"},
63	{struct{ x ([]int8) }{}, "[]int8"},
64	{struct{ x (map[string]int32) }{}, "map[string]int32"},
65	{struct{ x (chan<- string) }{}, "chan<- string"},
66	{struct {
67		x struct {
68			c chan *int32
69			d float32
70		}
71	}{},
72		"struct { c chan *int32; d float32 }",
73	},
74	{struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"},
75	{struct {
76		x struct {
77			c func(chan *integer, *int8)
78		}
79	}{},
80		"struct { c func(chan *reflectlite_test.integer, *int8) }",
81	},
82	{struct {
83		x struct {
84			a int8
85			b int32
86		}
87	}{},
88		"struct { a int8; b int32 }",
89	},
90	{struct {
91		x struct {
92			a int8
93			b int8
94			c int32
95		}
96	}{},
97		"struct { a int8; b int8; c int32 }",
98	},
99	{struct {
100		x struct {
101			a int8
102			b int8
103			c int8
104			d int32
105		}
106	}{},
107		"struct { a int8; b int8; c int8; d int32 }",
108	},
109	{struct {
110		x struct {
111			a int8
112			b int8
113			c int8
114			d int8
115			e int32
116		}
117	}{},
118		"struct { a int8; b int8; c int8; d int8; e int32 }",
119	},
120	{struct {
121		x struct {
122			a int8
123			b int8
124			c int8
125			d int8
126			e int8
127			f int32
128		}
129	}{},
130		"struct { a int8; b int8; c int8; d int8; e int8; f int32 }",
131	},
132	{struct {
133		x struct {
134			a int8 `reflect:"hi there"`
135		}
136	}{},
137		`struct { a int8 "reflect:\"hi there\"" }`,
138	},
139	{struct {
140		x struct {
141			a int8 `reflect:"hi \x00there\t\n\"\\"`
142		}
143	}{},
144		`struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`,
145	},
146	{struct {
147		x struct {
148			f func(args ...int)
149		}
150	}{},
151		"struct { f func(...int) }",
152	},
153	// {struct {
154	// 	x (interface {
155	// 		a(func(func(int) int) func(func(int)) int)
156	// 		b()
157	// 	})
158	// }{},
159	// 	"interface { reflectlite_test.a(func(func(int) int) func(func(int)) int); reflectlite_test.b() }",
160	// },
161	{struct {
162		x struct {
163			int32
164			int64
165		}
166	}{},
167		"struct { int32; int64 }",
168	},
169}
170
171var valueTests = []pair{
172	{new(int), "132"},
173	{new(int8), "8"},
174	{new(int16), "16"},
175	{new(int32), "32"},
176	{new(int64), "64"},
177	{new(uint), "132"},
178	{new(uint8), "8"},
179	{new(uint16), "16"},
180	{new(uint32), "32"},
181	{new(uint64), "64"},
182	{new(float32), "256.25"},
183	{new(float64), "512.125"},
184	{new(complex64), "532.125+10i"},
185	{new(complex128), "564.25+1i"},
186	{new(string), "stringy cheese"},
187	{new(bool), "true"},
188	{new(*int8), "*int8(0)"},
189	{new(**int8), "**int8(0)"},
190	{new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
191	{new(**integer), "**reflectlite_test.integer(0)"},
192	{new(map[string]int32), "map[string]int32{<can't iterate on maps>}"},
193	{new(chan<- string), "chan<- string"},
194	{new(func(a int8, b int32)), "func(int8, int32)(arg)"},
195	{new(struct {
196		c chan *int32
197		d float32
198	}),
199		"struct { c chan *int32; d float32 }{chan *int32, 0}",
200	},
201	{new(struct{ c func(chan *integer, *int8) }),
202		"struct { c func(chan *reflectlite_test.integer, *int8) }{func(chan *reflectlite_test.integer, *int8)(arg)}",
203	},
204	{new(struct {
205		a int8
206		b int32
207	}),
208		"struct { a int8; b int32 }{0, 0}",
209	},
210	{new(struct {
211		a int8
212		b int8
213		c int32
214	}),
215		"struct { a int8; b int8; c int32 }{0, 0, 0}",
216	},
217}
218
219func testType(t *testing.T, i int, typ Type, want string) {
220	s := TypeString(typ)
221	if s != want {
222		t.Errorf("#%d: have %#q, want %#q", i, s, want)
223	}
224}
225
226func testReflectType(t *testing.T, i int, typ Type, want string) {
227	s := TypeString(typ)
228	if s != want {
229		t.Errorf("#%d: have %#q, want %#q", i, s, want)
230	}
231}
232
233func TestTypes(t *testing.T) {
234	for i, tt := range typeTests {
235		testReflectType(t, i, Field(ValueOf(tt.i), 0).Type(), tt.s)
236	}
237}
238
239func TestSetValue(t *testing.T) {
240	for i, tt := range valueTests {
241		v := ValueOf(tt.i).Elem()
242		switch v.Kind() {
243		case Int:
244			v.Set(ValueOf(int(132)))
245		case Int8:
246			v.Set(ValueOf(int8(8)))
247		case Int16:
248			v.Set(ValueOf(int16(16)))
249		case Int32:
250			v.Set(ValueOf(int32(32)))
251		case Int64:
252			v.Set(ValueOf(int64(64)))
253		case Uint:
254			v.Set(ValueOf(uint(132)))
255		case Uint8:
256			v.Set(ValueOf(uint8(8)))
257		case Uint16:
258			v.Set(ValueOf(uint16(16)))
259		case Uint32:
260			v.Set(ValueOf(uint32(32)))
261		case Uint64:
262			v.Set(ValueOf(uint64(64)))
263		case Float32:
264			v.Set(ValueOf(float32(256.25)))
265		case Float64:
266			v.Set(ValueOf(512.125))
267		case Complex64:
268			v.Set(ValueOf(complex64(532.125 + 10i)))
269		case Complex128:
270			v.Set(ValueOf(complex128(564.25 + 1i)))
271		case String:
272			v.Set(ValueOf("stringy cheese"))
273		case Bool:
274			v.Set(ValueOf(true))
275		}
276		s := valueToString(v)
277		if s != tt.s {
278			t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
279		}
280	}
281}
282
283func TestCanSetField(t *testing.T) {
284	type embed struct{ x, X int }
285	type Embed struct{ x, X int }
286	type S1 struct {
287		embed
288		x, X int
289	}
290	type S2 struct {
291		*embed
292		x, X int
293	}
294	type S3 struct {
295		Embed
296		x, X int
297	}
298	type S4 struct {
299		*Embed
300		x, X int
301	}
302
303	type testCase struct {
304		index  []int
305		canSet bool
306	}
307	tests := []struct {
308		val   Value
309		cases []testCase
310	}{{
311		val: ValueOf(&S1{}),
312		cases: []testCase{
313			{[]int{0}, false},
314			{[]int{0, 0}, false},
315			{[]int{0, 1}, true},
316			{[]int{1}, false},
317			{[]int{2}, true},
318		},
319	}, {
320		val: ValueOf(&S2{embed: &embed{}}),
321		cases: []testCase{
322			{[]int{0}, false},
323			{[]int{0, 0}, false},
324			{[]int{0, 1}, true},
325			{[]int{1}, false},
326			{[]int{2}, true},
327		},
328	}, {
329		val: ValueOf(&S3{}),
330		cases: []testCase{
331			{[]int{0}, true},
332			{[]int{0, 0}, false},
333			{[]int{0, 1}, true},
334			{[]int{1}, false},
335			{[]int{2}, true},
336		},
337	}, {
338		val: ValueOf(&S4{Embed: &Embed{}}),
339		cases: []testCase{
340			{[]int{0}, true},
341			{[]int{0, 0}, false},
342			{[]int{0, 1}, true},
343			{[]int{1}, false},
344			{[]int{2}, true},
345		},
346	}}
347
348	for _, tt := range tests {
349		t.Run(tt.val.Type().Name(), func(t *testing.T) {
350			for _, tc := range tt.cases {
351				f := tt.val
352				for _, i := range tc.index {
353					if f.Kind() == Ptr {
354						f = f.Elem()
355					}
356					f = Field(f, i)
357				}
358				if got := f.CanSet(); got != tc.canSet {
359					t.Errorf("CanSet() = %v, want %v", got, tc.canSet)
360				}
361			}
362		})
363	}
364}
365
366var _i = 7
367
368var valueToStringTests = []pair{
369	{123, "123"},
370	{123.5, "123.5"},
371	{byte(123), "123"},
372	{"abc", "abc"},
373	{T{123, 456.75, "hello", &_i}, "reflectlite_test.T{123, 456.75, hello, *int(&7)}"},
374	{new(chan *T), "*chan *reflectlite_test.T(&chan *reflectlite_test.T)"},
375	{[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
376	{&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
377	{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
378	{&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
379}
380
381func TestValueToString(t *testing.T) {
382	for i, test := range valueToStringTests {
383		s := valueToString(ValueOf(test.i))
384		if s != test.s {
385			t.Errorf("#%d: have %#q, want %#q", i, s, test.s)
386		}
387	}
388}
389
390func TestPtrSetNil(t *testing.T) {
391	var i int32 = 1234
392	ip := &i
393	vip := ValueOf(&ip)
394	vip.Elem().Set(Zero(vip.Elem().Type()))
395	if ip != nil {
396		t.Errorf("got non-nil (%d), want nil", *ip)
397	}
398}
399
400func TestMapSetNil(t *testing.T) {
401	m := make(map[string]int)
402	vm := ValueOf(&m)
403	vm.Elem().Set(Zero(vm.Elem().Type()))
404	if m != nil {
405		t.Errorf("got non-nil (%p), want nil", m)
406	}
407}
408
409func TestAll(t *testing.T) {
410	testType(t, 1, TypeOf((int8)(0)), "int8")
411	testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8")
412
413	typ := TypeOf((*struct {
414		c chan *int32
415		d float32
416	})(nil))
417	testType(t, 3, typ, "*struct { c chan *int32; d float32 }")
418	etyp := typ.Elem()
419	testType(t, 4, etyp, "struct { c chan *int32; d float32 }")
420}
421
422func TestInterfaceValue(t *testing.T) {
423	var inter struct {
424		E any
425	}
426	inter.E = 123.456
427	v1 := ValueOf(&inter)
428	v2 := Field(v1.Elem(), 0)
429	// assert(t, TypeString(v2.Type()), "interface {}")
430	v3 := v2.Elem()
431	assert(t, TypeString(v3.Type()), "float64")
432
433	i3 := ToInterface(v2)
434	if _, ok := i3.(float64); !ok {
435		t.Error("v2.Interface() did not return float64, got ", TypeOf(i3))
436	}
437}
438
439func TestFunctionValue(t *testing.T) {
440	var x any = func() {}
441	v := ValueOf(x)
442	if fmt.Sprint(ToInterface(v)) != fmt.Sprint(x) {
443		t.Fatalf("TestFunction returned wrong pointer")
444	}
445	assert(t, TypeString(v.Type()), "func()")
446}
447
448var appendTests = []struct {
449	orig, extra []int
450}{
451	{make([]int, 2, 4), []int{22}},
452	{make([]int, 2, 4), []int{22, 33, 44}},
453}
454
455func sameInts(x, y []int) bool {
456	if len(x) != len(y) {
457		return false
458	}
459	for i, xx := range x {
460		if xx != y[i] {
461			return false
462		}
463	}
464	return true
465}
466
467func TestBigUnnamedStruct(t *testing.T) {
468	b := struct{ a, b, c, d int64 }{1, 2, 3, 4}
469	v := ValueOf(b)
470	b1 := ToInterface(v).(struct {
471		a, b, c, d int64
472	})
473	if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d {
474		t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1)
475	}
476}
477
478type big struct {
479	a, b, c, d, e int64
480}
481
482func TestBigStruct(t *testing.T) {
483	b := big{1, 2, 3, 4, 5}
484	v := ValueOf(b)
485	b1 := ToInterface(v).(big)
486	if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e {
487		t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1)
488	}
489}
490
491type Basic struct {
492	x int
493	y float32
494}
495
496type NotBasic Basic
497
498type DeepEqualTest struct {
499	a, b any
500	eq   bool
501}
502
503// Simple functions for DeepEqual tests.
504var (
505	fn1 func()             // nil.
506	fn2 func()             // nil.
507	fn3 = func() { fn1() } // Not nil.
508)
509
510type self struct{}
511
512type Loop *Loop
513type Loopy any
514
515var loop1, loop2 Loop
516var loopy1, loopy2 Loopy
517
518func init() {
519	loop1 = &loop2
520	loop2 = &loop1
521
522	loopy1 = &loopy2
523	loopy2 = &loopy1
524}
525
526var typeOfTests = []DeepEqualTest{
527	// Equalities
528	{nil, nil, true},
529	{1, 1, true},
530	{int32(1), int32(1), true},
531	{0.5, 0.5, true},
532	{float32(0.5), float32(0.5), true},
533	{"hello", "hello", true},
534	{make([]int, 10), make([]int, 10), true},
535	{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
536	{Basic{1, 0.5}, Basic{1, 0.5}, true},
537	{error(nil), error(nil), true},
538	{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
539	{fn1, fn2, true},
540
541	// Inequalities
542	{1, 2, false},
543	{int32(1), int32(2), false},
544	{0.5, 0.6, false},
545	{float32(0.5), float32(0.6), false},
546	{"hello", "hey", false},
547	{make([]int, 10), make([]int, 11), false},
548	{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
549	{Basic{1, 0.5}, Basic{1, 0.6}, false},
550	{Basic{1, 0}, Basic{2, 0}, false},
551	{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
552	{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
553	{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
554	{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
555	{nil, 1, false},
556	{1, nil, false},
557	{fn1, fn3, false},
558	{fn3, fn3, false},
559	{[][]int{{1}}, [][]int{{2}}, false},
560	{math.NaN(), math.NaN(), false},
561	{&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false},
562	{&[1]float64{math.NaN()}, self{}, true},
563	{[]float64{math.NaN()}, []float64{math.NaN()}, false},
564	{[]float64{math.NaN()}, self{}, true},
565	{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
566	{map[float64]float64{math.NaN(): 1}, self{}, true},
567
568	// Nil vs empty: not the same.
569	{[]int{}, []int(nil), false},
570	{[]int{}, []int{}, true},
571	{[]int(nil), []int(nil), true},
572	{map[int]int{}, map[int]int(nil), false},
573	{map[int]int{}, map[int]int{}, true},
574	{map[int]int(nil), map[int]int(nil), true},
575
576	// Mismatched types
577	{1, 1.0, false},
578	{int32(1), int64(1), false},
579	{0.5, "hello", false},
580	{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
581	{&[3]any{1, 2, 4}, &[3]any{1, 2, "s"}, false},
582	{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
583	{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
584
585	// Possible loops.
586	{&loop1, &loop1, true},
587	{&loop1, &loop2, true},
588	{&loopy1, &loopy1, true},
589	{&loopy1, &loopy2, true},
590}
591
592func TestTypeOf(t *testing.T) {
593	// Special case for nil
594	if typ := TypeOf(nil); typ != nil {
595		t.Errorf("expected nil type for nil value; got %v", typ)
596	}
597	for _, test := range typeOfTests {
598		v := ValueOf(test.a)
599		if !v.IsValid() {
600			continue
601		}
602		typ := TypeOf(test.a)
603		if typ != v.Type() {
604			t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type())
605		}
606	}
607}
608
609func Nil(a any, t *testing.T) {
610	n := Field(ValueOf(a), 0)
611	if !n.IsNil() {
612		t.Errorf("%v should be nil", a)
613	}
614}
615
616func NotNil(a any, t *testing.T) {
617	n := Field(ValueOf(a), 0)
618	if n.IsNil() {
619		t.Errorf("value of type %v should not be nil", TypeString(ValueOf(a).Type()))
620	}
621}
622
623func TestIsNil(t *testing.T) {
624	// These implement IsNil.
625	// Wrap in extra struct to hide interface type.
626	doNil := []any{
627		struct{ x *int }{},
628		struct{ x any }{},
629		struct{ x map[string]int }{},
630		struct{ x func() bool }{},
631		struct{ x chan int }{},
632		struct{ x []string }{},
633		struct{ x unsafe.Pointer }{},
634	}
635	for _, ts := range doNil {
636		ty := TField(TypeOf(ts), 0)
637		v := Zero(ty)
638		v.IsNil() // panics if not okay to call
639	}
640
641	// Check the implementations
642	var pi struct {
643		x *int
644	}
645	Nil(pi, t)
646	pi.x = new(int)
647	NotNil(pi, t)
648
649	var si struct {
650		x []int
651	}
652	Nil(si, t)
653	si.x = make([]int, 10)
654	NotNil(si, t)
655
656	var ci struct {
657		x chan int
658	}
659	Nil(ci, t)
660	ci.x = make(chan int)
661	NotNil(ci, t)
662
663	var mi struct {
664		x map[int]int
665	}
666	Nil(mi, t)
667	mi.x = make(map[int]int)
668	NotNil(mi, t)
669
670	var ii struct {
671		x any
672	}
673	Nil(ii, t)
674	ii.x = 2
675	NotNil(ii, t)
676
677	var fi struct {
678		x func(t *testing.T)
679	}
680	Nil(fi, t)
681	fi.x = TestIsNil
682	NotNil(fi, t)
683}
684
685// Indirect returns the value that v points to.
686// If v is a nil pointer, Indirect returns a zero Value.
687// If v is not a pointer, Indirect returns v.
688func Indirect(v Value) Value {
689	if v.Kind() != Ptr {
690		return v
691	}
692	return v.Elem()
693}
694
695func TestNilPtrValueSub(t *testing.T) {
696	var pi *int
697	if pv := ValueOf(pi); pv.Elem().IsValid() {
698		t.Error("ValueOf((*int)(nil)).Elem().IsValid()")
699	}
700}
701
702type Point struct {
703	x, y int
704}
705
706// This will be index 0.
707func (p Point) AnotherMethod(scale int) int {
708	return -1
709}
710
711// This will be index 1.
712func (p Point) Dist(scale int) int {
713	//println("Point.Dist", p.x, p.y, scale)
714	return p.x*p.x*scale + p.y*p.y*scale
715}
716
717// This will be index 2.
718func (p Point) GCMethod(k int) int {
719	runtime.GC()
720	return k + p.x
721}
722
723// This will be index 3.
724func (p Point) NoArgs() {
725	// Exercise no-argument/no-result paths.
726}
727
728// This will be index 4.
729func (p Point) TotalDist(points ...Point) int {
730	tot := 0
731	for _, q := range points {
732		dx := q.x - p.x
733		dy := q.y - p.y
734		tot += dx*dx + dy*dy // Should call Sqrt, but it's just a test.
735
736	}
737	return tot
738}
739
740type D1 struct {
741	d int
742}
743type D2 struct {
744	d int
745}
746
747func TestImportPath(t *testing.T) {
748	tests := []struct {
749		t    Type
750		path string
751	}{
752		{TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
753		{TypeOf(int(0)), ""},
754		{TypeOf(int8(0)), ""},
755		{TypeOf(int16(0)), ""},
756		{TypeOf(int32(0)), ""},
757		{TypeOf(int64(0)), ""},
758		{TypeOf(uint(0)), ""},
759		{TypeOf(uint8(0)), ""},
760		{TypeOf(uint16(0)), ""},
761		{TypeOf(uint32(0)), ""},
762		{TypeOf(uint64(0)), ""},
763		{TypeOf(uintptr(0)), ""},
764		{TypeOf(float32(0)), ""},
765		{TypeOf(float64(0)), ""},
766		{TypeOf(complex64(0)), ""},
767		{TypeOf(complex128(0)), ""},
768		{TypeOf(byte(0)), ""},
769		{TypeOf(rune(0)), ""},
770		{TypeOf([]byte(nil)), ""},
771		{TypeOf([]rune(nil)), ""},
772		{TypeOf(string("")), ""},
773		{TypeOf((*any)(nil)).Elem(), ""},
774		{TypeOf((*byte)(nil)), ""},
775		{TypeOf((*rune)(nil)), ""},
776		{TypeOf((*int64)(nil)), ""},
777		{TypeOf(map[string]int{}), ""},
778		{TypeOf((*error)(nil)).Elem(), ""},
779		{TypeOf((*Point)(nil)), ""},
780		{TypeOf((*Point)(nil)).Elem(), "internal/reflectlite_test"},
781	}
782	for _, test := range tests {
783		if path := test.t.PkgPath(); path != test.path {
784			t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path)
785		}
786	}
787}
788
789func noAlloc(t *testing.T, n int, f func(int)) {
790	if testing.Short() {
791		t.Skip("skipping malloc count in short mode")
792	}
793	if runtime.GOMAXPROCS(0) > 1 {
794		t.Skip("skipping; GOMAXPROCS>1")
795	}
796	i := -1
797	allocs := testing.AllocsPerRun(n, func() {
798		f(i)
799		i++
800	})
801	if allocs > 0 {
802		t.Errorf("%d iterations: got %v mallocs, want 0", n, allocs)
803	}
804}
805
806func TestAllocations(t *testing.T) {
807	noAlloc(t, 100, func(j int) {
808		var i any
809		var v Value
810
811		// We can uncomment this when compiler escape analysis
812		// is good enough to see that the integer assigned to i
813		// does not escape and therefore need not be allocated.
814		//
815		// i = 42 + j
816		// v = ValueOf(i)
817		// if int(v.Int()) != 42+j {
818		// 	panic("wrong int")
819		// }
820
821		i = func(j int) int { return j }
822		v = ValueOf(i)
823		if ToInterface(v).(func(int) int)(j) != j {
824			panic("wrong result")
825		}
826	})
827}
828
829func TestSetPanic(t *testing.T) {
830	ok := func(f func()) { f() }
831	bad := shouldPanic
832	clear := func(v Value) { v.Set(Zero(v.Type())) }
833
834	type t0 struct {
835		W int
836	}
837
838	type t1 struct {
839		Y int
840		t0
841	}
842
843	type T2 struct {
844		Z       int
845		namedT0 t0
846	}
847
848	type T struct {
849		X int
850		t1
851		T2
852		NamedT1 t1
853		NamedT2 T2
854		namedT1 t1
855		namedT2 T2
856	}
857
858	// not addressable
859	v := ValueOf(T{})
860	bad(func() { clear(Field(v, 0)) })                     // .X
861	bad(func() { clear(Field(v, 1)) })                     // .t1
862	bad(func() { clear(Field(Field(v, 1), 0)) })           // .t1.Y
863	bad(func() { clear(Field(Field(v, 1), 1)) })           // .t1.t0
864	bad(func() { clear(Field(Field(Field(v, 1), 1), 0)) }) // .t1.t0.W
865	bad(func() { clear(Field(v, 2)) })                     // .T2
866	bad(func() { clear(Field(Field(v, 2), 0)) })           // .T2.Z
867	bad(func() { clear(Field(Field(v, 2), 1)) })           // .T2.namedT0
868	bad(func() { clear(Field(Field(Field(v, 2), 1), 0)) }) // .T2.namedT0.W
869	bad(func() { clear(Field(v, 3)) })                     // .NamedT1
870	bad(func() { clear(Field(Field(v, 3), 0)) })           // .NamedT1.Y
871	bad(func() { clear(Field(Field(v, 3), 1)) })           // .NamedT1.t0
872	bad(func() { clear(Field(Field(Field(v, 3), 1), 0)) }) // .NamedT1.t0.W
873	bad(func() { clear(Field(v, 4)) })                     // .NamedT2
874	bad(func() { clear(Field(Field(v, 4), 0)) })           // .NamedT2.Z
875	bad(func() { clear(Field(Field(v, 4), 1)) })           // .NamedT2.namedT0
876	bad(func() { clear(Field(Field(Field(v, 4), 1), 0)) }) // .NamedT2.namedT0.W
877	bad(func() { clear(Field(v, 5)) })                     // .namedT1
878	bad(func() { clear(Field(Field(v, 5), 0)) })           // .namedT1.Y
879	bad(func() { clear(Field(Field(v, 5), 1)) })           // .namedT1.t0
880	bad(func() { clear(Field(Field(Field(v, 5), 1), 0)) }) // .namedT1.t0.W
881	bad(func() { clear(Field(v, 6)) })                     // .namedT2
882	bad(func() { clear(Field(Field(v, 6), 0)) })           // .namedT2.Z
883	bad(func() { clear(Field(Field(v, 6), 1)) })           // .namedT2.namedT0
884	bad(func() { clear(Field(Field(Field(v, 6), 1), 0)) }) // .namedT2.namedT0.W
885
886	// addressable
887	v = ValueOf(&T{}).Elem()
888	ok(func() { clear(Field(v, 0)) })                      // .X
889	bad(func() { clear(Field(v, 1)) })                     // .t1
890	ok(func() { clear(Field(Field(v, 1), 0)) })            // .t1.Y
891	bad(func() { clear(Field(Field(v, 1), 1)) })           // .t1.t0
892	ok(func() { clear(Field(Field(Field(v, 1), 1), 0)) })  // .t1.t0.W
893	ok(func() { clear(Field(v, 2)) })                      // .T2
894	ok(func() { clear(Field(Field(v, 2), 0)) })            // .T2.Z
895	bad(func() { clear(Field(Field(v, 2), 1)) })           // .T2.namedT0
896	bad(func() { clear(Field(Field(Field(v, 2), 1), 0)) }) // .T2.namedT0.W
897	ok(func() { clear(Field(v, 3)) })                      // .NamedT1
898	ok(func() { clear(Field(Field(v, 3), 0)) })            // .NamedT1.Y
899	bad(func() { clear(Field(Field(v, 3), 1)) })           // .NamedT1.t0
900	ok(func() { clear(Field(Field(Field(v, 3), 1), 0)) })  // .NamedT1.t0.W
901	ok(func() { clear(Field(v, 4)) })                      // .NamedT2
902	ok(func() { clear(Field(Field(v, 4), 0)) })            // .NamedT2.Z
903	bad(func() { clear(Field(Field(v, 4), 1)) })           // .NamedT2.namedT0
904	bad(func() { clear(Field(Field(Field(v, 4), 1), 0)) }) // .NamedT2.namedT0.W
905	bad(func() { clear(Field(v, 5)) })                     // .namedT1
906	bad(func() { clear(Field(Field(v, 5), 0)) })           // .namedT1.Y
907	bad(func() { clear(Field(Field(v, 5), 1)) })           // .namedT1.t0
908	bad(func() { clear(Field(Field(Field(v, 5), 1), 0)) }) // .namedT1.t0.W
909	bad(func() { clear(Field(v, 6)) })                     // .namedT2
910	bad(func() { clear(Field(Field(v, 6), 0)) })           // .namedT2.Z
911	bad(func() { clear(Field(Field(v, 6), 1)) })           // .namedT2.namedT0
912	bad(func() { clear(Field(Field(Field(v, 6), 1), 0)) }) // .namedT2.namedT0.W
913}
914
915func shouldPanic(f func()) {
916	defer func() {
917		if recover() == nil {
918			panic("did not panic")
919		}
920	}()
921	f()
922}
923
924type S struct {
925	i1 int64
926	i2 int64
927}
928
929func TestBigZero(t *testing.T) {
930	const size = 1 << 10
931	var v [size]byte
932	z := ToInterface(Zero(ValueOf(v).Type())).([size]byte)
933	for i := 0; i < size; i++ {
934		if z[i] != 0 {
935			t.Fatalf("Zero object not all zero, index %d", i)
936		}
937	}
938}
939
940func TestInvalid(t *testing.T) {
941	// Used to have inconsistency between IsValid() and Kind() != Invalid.
942	type T struct{ v any }
943
944	v := Field(ValueOf(T{}), 0)
945	if v.IsValid() != true || v.Kind() != Interface {
946		t.Errorf("field: IsValid=%v, Kind=%v, want true, Interface", v.IsValid(), v.Kind())
947	}
948	v = v.Elem()
949	if v.IsValid() != false || v.Kind() != Invalid {
950		t.Errorf("field elem: IsValid=%v, Kind=%v, want false, Invalid", v.IsValid(), v.Kind())
951	}
952}
953
954type TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678 int
955
956type nameTest struct {
957	v    any
958	want string
959}
960
961var nameTests = []nameTest{
962	{(*int32)(nil), "int32"},
963	{(*D1)(nil), "D1"},
964	{(*[]D1)(nil), ""},
965	{(*chan D1)(nil), ""},
966	{(*func() D1)(nil), ""},
967	{(*<-chan D1)(nil), ""},
968	{(*chan<- D1)(nil), ""},
969	{(*any)(nil), ""},
970	{(*interface {
971		F()
972	})(nil), ""},
973	{(*TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678)(nil), "TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678"},
974}
975
976func TestNames(t *testing.T) {
977	for _, test := range nameTests {
978		typ := TypeOf(test.v).Elem()
979		if got := typ.Name(); got != test.want {
980			t.Errorf("%v Name()=%q, want %q", typ, got, test.want)
981		}
982	}
983}
984
985// TestUnaddressableField tests that the reflect package will not allow
986// a type from another package to be used as a named type with an
987// unexported field.
988//
989// This ensures that unexported fields cannot be modified by other packages.
990func TestUnaddressableField(t *testing.T) {
991	var b Buffer // type defined in reflect, a different package
992	var localBuffer struct {
993		buf []byte
994	}
995	lv := ValueOf(&localBuffer).Elem()
996	rv := ValueOf(b)
997	shouldPanic(func() {
998		lv.Set(rv)
999	})
1000}
1001
1002type Tint int
1003
1004type Tint2 = Tint
1005
1006type Talias1 struct {
1007	byte
1008	uint8
1009	int
1010	int32
1011	rune
1012}
1013
1014type Talias2 struct {
1015	Tint
1016	Tint2
1017}
1018
1019func TestAliasNames(t *testing.T) {
1020	t1 := Talias1{byte: 1, uint8: 2, int: 3, int32: 4, rune: 5}
1021	out := fmt.Sprintf("%#v", t1)
1022	want := "reflectlite_test.Talias1{byte:0x1, uint8:0x2, int:3, int32:4, rune:5}"
1023	if out != want {
1024		t.Errorf("Talias1 print:\nhave: %s\nwant: %s", out, want)
1025	}
1026
1027	t2 := Talias2{Tint: 1, Tint2: 2}
1028	out = fmt.Sprintf("%#v", t2)
1029	want = "reflectlite_test.Talias2{Tint:1, Tint2:2}"
1030	if out != want {
1031		t.Errorf("Talias2 print:\nhave: %s\nwant: %s", out, want)
1032	}
1033}
1034