Source file src/internal/reflectlite/all_test.go

     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  
     5  package reflectlite_test
     6  
     7  import (
     8  	"encoding/base64"
     9  	"fmt"
    10  	. "internal/reflectlite"
    11  	"math"
    12  	"reflect"
    13  	"runtime"
    14  	"testing"
    15  	"unsafe"
    16  )
    17  
    18  func ToValue(v Value) reflect.Value {
    19  	return reflect.ValueOf(ToInterface(v))
    20  }
    21  
    22  func TypeString(t Type) string {
    23  	return fmt.Sprintf("%T", ToInterface(Zero(t)))
    24  }
    25  
    26  type integer int
    27  type T struct {
    28  	a int
    29  	b float64
    30  	c string
    31  	d *int
    32  }
    33  
    34  type pair struct {
    35  	i any
    36  	s string
    37  }
    38  
    39  func 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  
    46  var 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  
   171  var 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  
   219  func 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  
   226  func 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  
   233  func 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  
   239  func 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  
   283  func 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  
   366  var _i = 7
   367  
   368  var 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  
   381  func 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  
   390  func 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  
   400  func 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  
   409  func 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  
   422  func 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  
   439  func 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  
   448  var 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  
   455  func 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  
   467  func 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  
   478  type big struct {
   479  	a, b, c, d, e int64
   480  }
   481  
   482  func 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  
   491  type Basic struct {
   492  	x int
   493  	y float32
   494  }
   495  
   496  type NotBasic Basic
   497  
   498  type DeepEqualTest struct {
   499  	a, b any
   500  	eq   bool
   501  }
   502  
   503  // Simple functions for DeepEqual tests.
   504  var (
   505  	fn1 func()             // nil.
   506  	fn2 func()             // nil.
   507  	fn3 = func() { fn1() } // Not nil.
   508  )
   509  
   510  type self struct{}
   511  
   512  type Loop *Loop
   513  type Loopy any
   514  
   515  var loop1, loop2 Loop
   516  var loopy1, loopy2 Loopy
   517  
   518  func init() {
   519  	loop1 = &loop2
   520  	loop2 = &loop1
   521  
   522  	loopy1 = &loopy2
   523  	loopy2 = &loopy1
   524  }
   525  
   526  var 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  
   592  func 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  
   609  func 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  
   616  func 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  
   623  func 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.
   688  func Indirect(v Value) Value {
   689  	if v.Kind() != Ptr {
   690  		return v
   691  	}
   692  	return v.Elem()
   693  }
   694  
   695  func 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  
   702  type Point struct {
   703  	x, y int
   704  }
   705  
   706  // This will be index 0.
   707  func (p Point) AnotherMethod(scale int) int {
   708  	return -1
   709  }
   710  
   711  // This will be index 1.
   712  func (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.
   718  func (p Point) GCMethod(k int) int {
   719  	runtime.GC()
   720  	return k + p.x
   721  }
   722  
   723  // This will be index 3.
   724  func (p Point) NoArgs() {
   725  	// Exercise no-argument/no-result paths.
   726  }
   727  
   728  // This will be index 4.
   729  func (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  
   740  type D1 struct {
   741  	d int
   742  }
   743  type D2 struct {
   744  	d int
   745  }
   746  
   747  func 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  
   789  func 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  
   806  func 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  
   829  func 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  
   915  func shouldPanic(f func()) {
   916  	defer func() {
   917  		if recover() == nil {
   918  			panic("did not panic")
   919  		}
   920  	}()
   921  	f()
   922  }
   923  
   924  type S struct {
   925  	i1 int64
   926  	i2 int64
   927  }
   928  
   929  func 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  
   940  func 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  
   954  type TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678 int
   955  
   956  type nameTest struct {
   957  	v    any
   958  	want string
   959  }
   960  
   961  var 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  
   976  func 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.
   990  func 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  
  1002  type Tint int
  1003  
  1004  type Tint2 = Tint
  1005  
  1006  type Talias1 struct {
  1007  	byte
  1008  	uint8
  1009  	int
  1010  	int32
  1011  	rune
  1012  }
  1013  
  1014  type Talias2 struct {
  1015  	Tint
  1016  	Tint2
  1017  }
  1018  
  1019  func 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  

View as plain text