// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package reflectlite_test import ( "encoding/base64" "fmt" . "internal/reflectlite" "math" "reflect" "runtime" "testing" "unsafe" ) func ToValue(v Value) reflect.Value { return reflect.ValueOf(ToInterface(v)) } func TypeString(t Type) string { return fmt.Sprintf("%T", ToInterface(Zero(t))) } type integer int type T struct { a int b float64 c string d *int } type pair struct { i interface{} s string } func assert(t *testing.T, s, want string) { t.Helper() if s != want { t.Errorf("have %#q want %#q", s, want) } } var typeTests = []pair{ {struct{ x int }{}, "int"}, {struct{ x int8 }{}, "int8"}, {struct{ x int16 }{}, "int16"}, {struct{ x int32 }{}, "int32"}, {struct{ x int64 }{}, "int64"}, {struct{ x uint }{}, "uint"}, {struct{ x uint8 }{}, "uint8"}, {struct{ x uint16 }{}, "uint16"}, {struct{ x uint32 }{}, "uint32"}, {struct{ x uint64 }{}, "uint64"}, {struct{ x float32 }{}, "float32"}, {struct{ x float64 }{}, "float64"}, {struct{ x int8 }{}, "int8"}, {struct{ x (**int8) }{}, "**int8"}, {struct{ x (**integer) }{}, "**reflectlite_test.integer"}, {struct{ x ([32]int32) }{}, "[32]int32"}, {struct{ x ([]int8) }{}, "[]int8"}, {struct{ x (map[string]int32) }{}, "map[string]int32"}, {struct{ x (chan<- string) }{}, "chan<- string"}, {struct { x struct { c chan *int32 d float32 } }{}, "struct { c chan *int32; d float32 }", }, {struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"}, {struct { x struct { c func(chan *integer, *int8) } }{}, "struct { c func(chan *reflectlite_test.integer, *int8) }", }, {struct { x struct { a int8 b int32 } }{}, "struct { a int8; b int32 }", }, {struct { x struct { a int8 b int8 c int32 } }{}, "struct { a int8; b int8; c int32 }", }, {struct { x struct { a int8 b int8 c int8 d int32 } }{}, "struct { a int8; b int8; c int8; d int32 }", }, {struct { x struct { a int8 b int8 c int8 d int8 e int32 } }{}, "struct { a int8; b int8; c int8; d int8; e int32 }", }, {struct { x struct { a int8 b int8 c int8 d int8 e int8 f int32 } }{}, "struct { a int8; b int8; c int8; d int8; e int8; f int32 }", }, {struct { x struct { a int8 `reflect:"hi there"` } }{}, `struct { a int8 "reflect:\"hi there\"" }`, }, {struct { x struct { a int8 `reflect:"hi \x00there\t\n\"\\"` } }{}, `struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`, }, {struct { x struct { f func(args ...int) } }{}, "struct { f func(...int) }", }, // {struct { // x (interface { // a(func(func(int) int) func(func(int)) int) // b() // }) // }{}, // "interface { reflectlite_test.a(func(func(int) int) func(func(int)) int); reflectlite_test.b() }", // }, {struct { x struct { int32 int64 } }{}, "struct { int32; int64 }", }, } var valueTests = []pair{ {new(int), "132"}, {new(int8), "8"}, {new(int16), "16"}, {new(int32), "32"}, {new(int64), "64"}, {new(uint), "132"}, {new(uint8), "8"}, {new(uint16), "16"}, {new(uint32), "32"}, {new(uint64), "64"}, {new(float32), "256.25"}, {new(float64), "512.125"}, {new(complex64), "532.125+10i"}, {new(complex128), "564.25+1i"}, {new(string), "stringy cheese"}, {new(bool), "true"}, {new(*int8), "*int8(0)"}, {new(**int8), "**int8(0)"}, {new([5]int32), "[5]int32{0, 0, 0, 0, 0}"}, {new(**integer), "**reflectlite_test.integer(0)"}, {new(map[string]int32), "map[string]int32{}"}, {new(chan<- string), "chan<- string"}, {new(func(a int8, b int32)), "func(int8, int32)(arg)"}, {new(struct { c chan *int32 d float32 }), "struct { c chan *int32; d float32 }{chan *int32, 0}", }, {new(struct{ c func(chan *integer, *int8) }), "struct { c func(chan *reflectlite_test.integer, *int8) }{func(chan *reflectlite_test.integer, *int8)(arg)}", }, {new(struct { a int8 b int32 }), "struct { a int8; b int32 }{0, 0}", }, {new(struct { a int8 b int8 c int32 }), "struct { a int8; b int8; c int32 }{0, 0, 0}", }, } func testType(t *testing.T, i int, typ Type, want string) { s := TypeString(typ) if s != want { t.Errorf("#%d: have %#q, want %#q", i, s, want) } } func testReflectType(t *testing.T, i int, typ Type, want string) { s := TypeString(typ) if s != want { t.Errorf("#%d: have %#q, want %#q", i, s, want) } } func TestTypes(t *testing.T) { for i, tt := range typeTests { testReflectType(t, i, Field(ValueOf(tt.i), 0).Type(), tt.s) } } func TestSetValue(t *testing.T) { for i, tt := range valueTests { v := ValueOf(tt.i).Elem() switch v.Kind() { case Int: v.Set(ValueOf(int(132))) case Int8: v.Set(ValueOf(int8(8))) case Int16: v.Set(ValueOf(int16(16))) case Int32: v.Set(ValueOf(int32(32))) case Int64: v.Set(ValueOf(int64(64))) case Uint: v.Set(ValueOf(uint(132))) case Uint8: v.Set(ValueOf(uint8(8))) case Uint16: v.Set(ValueOf(uint16(16))) case Uint32: v.Set(ValueOf(uint32(32))) case Uint64: v.Set(ValueOf(uint64(64))) case Float32: v.Set(ValueOf(float32(256.25))) case Float64: v.Set(ValueOf(512.125)) case Complex64: v.Set(ValueOf(complex64(532.125 + 10i))) case Complex128: v.Set(ValueOf(complex128(564.25 + 1i))) case String: v.Set(ValueOf("stringy cheese")) case Bool: v.Set(ValueOf(true)) } s := valueToString(v) if s != tt.s { t.Errorf("#%d: have %#q, want %#q", i, s, tt.s) } } } func TestCanSetField(t *testing.T) { type embed struct{ x, X int } type Embed struct{ x, X int } type S1 struct { embed x, X int } type S2 struct { *embed x, X int } type S3 struct { Embed x, X int } type S4 struct { *Embed x, X int } type testCase struct { index []int canSet bool } tests := []struct { val Value cases []testCase }{{ val: ValueOf(&S1{}), cases: []testCase{ {[]int{0}, false}, {[]int{0, 0}, false}, {[]int{0, 1}, true}, {[]int{1}, false}, {[]int{2}, true}, }, }, { val: ValueOf(&S2{embed: &embed{}}), cases: []testCase{ {[]int{0}, false}, {[]int{0, 0}, false}, {[]int{0, 1}, true}, {[]int{1}, false}, {[]int{2}, true}, }, }, { val: ValueOf(&S3{}), cases: []testCase{ {[]int{0}, true}, {[]int{0, 0}, false}, {[]int{0, 1}, true}, {[]int{1}, false}, {[]int{2}, true}, }, }, { val: ValueOf(&S4{Embed: &Embed{}}), cases: []testCase{ {[]int{0}, true}, {[]int{0, 0}, false}, {[]int{0, 1}, true}, {[]int{1}, false}, {[]int{2}, true}, }, }} for _, tt := range tests { t.Run(tt.val.Type().Name(), func(t *testing.T) { for _, tc := range tt.cases { f := tt.val for _, i := range tc.index { if f.Kind() == Ptr { f = f.Elem() } f = Field(f, i) } if got := f.CanSet(); got != tc.canSet { t.Errorf("CanSet() = %v, want %v", got, tc.canSet) } } }) } } var _i = 7 var valueToStringTests = []pair{ {123, "123"}, {123.5, "123.5"}, {byte(123), "123"}, {"abc", "abc"}, {T{123, 456.75, "hello", &_i}, "reflectlite_test.T{123, 456.75, hello, *int(&7)}"}, {new(chan *T), "*chan *reflectlite_test.T(&chan *reflectlite_test.T)"}, {[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"}, {&[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})"}, {[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"}, {&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"}, } func TestValueToString(t *testing.T) { for i, test := range valueToStringTests { s := valueToString(ValueOf(test.i)) if s != test.s { t.Errorf("#%d: have %#q, want %#q", i, s, test.s) } } } func TestPtrSetNil(t *testing.T) { var i int32 = 1234 ip := &i vip := ValueOf(&ip) vip.Elem().Set(Zero(vip.Elem().Type())) if ip != nil { t.Errorf("got non-nil (%d), want nil", *ip) } } func TestMapSetNil(t *testing.T) { m := make(map[string]int) vm := ValueOf(&m) vm.Elem().Set(Zero(vm.Elem().Type())) if m != nil { t.Errorf("got non-nil (%p), want nil", m) } } func TestAll(t *testing.T) { testType(t, 1, TypeOf((int8)(0)), "int8") testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8") typ := TypeOf((*struct { c chan *int32 d float32 })(nil)) testType(t, 3, typ, "*struct { c chan *int32; d float32 }") etyp := typ.Elem() testType(t, 4, etyp, "struct { c chan *int32; d float32 }") } func TestInterfaceValue(t *testing.T) { var inter struct { E interface{} } inter.E = 123.456 v1 := ValueOf(&inter) v2 := Field(v1.Elem(), 0) // assert(t, TypeString(v2.Type()), "interface {}") v3 := v2.Elem() assert(t, TypeString(v3.Type()), "float64") i3 := ToInterface(v2) if _, ok := i3.(float64); !ok { t.Error("v2.Interface() did not return float64, got ", TypeOf(i3)) } } func TestFunctionValue(t *testing.T) { var x interface{} = func() {} v := ValueOf(x) if fmt.Sprint(ToInterface(v)) != fmt.Sprint(x) { t.Fatalf("TestFunction returned wrong pointer") } assert(t, TypeString(v.Type()), "func()") } var appendTests = []struct { orig, extra []int }{ {make([]int, 2, 4), []int{22}}, {make([]int, 2, 4), []int{22, 33, 44}}, } func sameInts(x, y []int) bool { if len(x) != len(y) { return false } for i, xx := range x { if xx != y[i] { return false } } return true } func TestBigUnnamedStruct(t *testing.T) { b := struct{ a, b, c, d int64 }{1, 2, 3, 4} v := ValueOf(b) b1 := ToInterface(v).(struct { a, b, c, d int64 }) if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d { t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1) } } type big struct { a, b, c, d, e int64 } func TestBigStruct(t *testing.T) { b := big{1, 2, 3, 4, 5} v := ValueOf(b) b1 := ToInterface(v).(big) if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e { t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1) } } type Basic struct { x int y float32 } type NotBasic Basic type DeepEqualTest struct { a, b interface{} eq bool } // Simple functions for DeepEqual tests. var ( fn1 func() // nil. fn2 func() // nil. fn3 = func() { fn1() } // Not nil. ) type self struct{} type Loop *Loop type Loopy interface{} var loop1, loop2 Loop var loopy1, loopy2 Loopy func init() { loop1 = &loop2 loop2 = &loop1 loopy1 = &loopy2 loopy2 = &loopy1 } var typeOfTests = []DeepEqualTest{ // Equalities {nil, nil, true}, {1, 1, true}, {int32(1), int32(1), true}, {0.5, 0.5, true}, {float32(0.5), float32(0.5), true}, {"hello", "hello", true}, {make([]int, 10), make([]int, 10), true}, {&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true}, {Basic{1, 0.5}, Basic{1, 0.5}, true}, {error(nil), error(nil), true}, {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true}, {fn1, fn2, true}, // Inequalities {1, 2, false}, {int32(1), int32(2), false}, {0.5, 0.6, false}, {float32(0.5), float32(0.6), false}, {"hello", "hey", false}, {make([]int, 10), make([]int, 11), false}, {&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false}, {Basic{1, 0.5}, Basic{1, 0.6}, false}, {Basic{1, 0}, Basic{2, 0}, false}, {map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false}, {map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false}, {map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false}, {map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false}, {nil, 1, false}, {1, nil, false}, {fn1, fn3, false}, {fn3, fn3, false}, {[][]int{{1}}, [][]int{{2}}, false}, {math.NaN(), math.NaN(), false}, {&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false}, {&[1]float64{math.NaN()}, self{}, true}, {[]float64{math.NaN()}, []float64{math.NaN()}, false}, {[]float64{math.NaN()}, self{}, true}, {map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false}, {map[float64]float64{math.NaN(): 1}, self{}, true}, // Nil vs empty: not the same. {[]int{}, []int(nil), false}, {[]int{}, []int{}, true}, {[]int(nil), []int(nil), true}, {map[int]int{}, map[int]int(nil), false}, {map[int]int{}, map[int]int{}, true}, {map[int]int(nil), map[int]int(nil), true}, // Mismatched types {1, 1.0, false}, {int32(1), int64(1), false}, {0.5, "hello", false}, {[]int{1, 2, 3}, [3]int{1, 2, 3}, false}, {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, // Possible loops. {&loop1, &loop1, true}, {&loop1, &loop2, true}, {&loopy1, &loopy1, true}, {&loopy1, &loopy2, true}, } func TestTypeOf(t *testing.T) { // Special case for nil if typ := TypeOf(nil); typ != nil { t.Errorf("expected nil type for nil value; got %v", typ) } for _, test := range typeOfTests { v := ValueOf(test.a) if !v.IsValid() { continue } typ := TypeOf(test.a) if typ != v.Type() { t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type()) } } } func Nil(a interface{}, t *testing.T) { n := Field(ValueOf(a), 0) if !n.IsNil() { t.Errorf("%v should be nil", a) } } func NotNil(a interface{}, t *testing.T) { n := Field(ValueOf(a), 0) if n.IsNil() { t.Errorf("value of type %v should not be nil", TypeString(ValueOf(a).Type())) } } func TestIsNil(t *testing.T) { // These implement IsNil. // Wrap in extra struct to hide interface type. doNil := []interface{}{ struct{ x *int }{}, struct{ x interface{} }{}, struct{ x map[string]int }{}, struct{ x func() bool }{}, struct{ x chan int }{}, struct{ x []string }{}, struct{ x unsafe.Pointer }{}, } for _, ts := range doNil { ty := TField(TypeOf(ts), 0) v := Zero(ty) v.IsNil() // panics if not okay to call } // Check the implementations var pi struct { x *int } Nil(pi, t) pi.x = new(int) NotNil(pi, t) var si struct { x []int } Nil(si, t) si.x = make([]int, 10) NotNil(si, t) var ci struct { x chan int } Nil(ci, t) ci.x = make(chan int) NotNil(ci, t) var mi struct { x map[int]int } Nil(mi, t) mi.x = make(map[int]int) NotNil(mi, t) var ii struct { x interface{} } Nil(ii, t) ii.x = 2 NotNil(ii, t) var fi struct { x func(t *testing.T) } Nil(fi, t) fi.x = TestIsNil NotNil(fi, t) } // Indirect returns the value that v points to. // If v is a nil pointer, Indirect returns a zero Value. // If v is not a pointer, Indirect returns v. func Indirect(v Value) Value { if v.Kind() != Ptr { return v } return v.Elem() } func TestNilPtrValueSub(t *testing.T) { var pi *int if pv := ValueOf(pi); pv.Elem().IsValid() { t.Error("ValueOf((*int)(nil)).Elem().IsValid()") } } type Point struct { x, y int } // This will be index 0. func (p Point) AnotherMethod(scale int) int { return -1 } // This will be index 1. func (p Point) Dist(scale int) int { //println("Point.Dist", p.x, p.y, scale) return p.x*p.x*scale + p.y*p.y*scale } // This will be index 2. func (p Point) GCMethod(k int) int { runtime.GC() return k + p.x } // This will be index 3. func (p Point) NoArgs() { // Exercise no-argument/no-result paths. } // This will be index 4. func (p Point) TotalDist(points ...Point) int { tot := 0 for _, q := range points { dx := q.x - p.x dy := q.y - p.y tot += dx*dx + dy*dy // Should call Sqrt, but it's just a test. } return tot } type D1 struct { d int } type D2 struct { d int } func TestImportPath(t *testing.T) { tests := []struct { t Type path string }{ {TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"}, {TypeOf(int(0)), ""}, {TypeOf(int8(0)), ""}, {TypeOf(int16(0)), ""}, {TypeOf(int32(0)), ""}, {TypeOf(int64(0)), ""}, {TypeOf(uint(0)), ""}, {TypeOf(uint8(0)), ""}, {TypeOf(uint16(0)), ""}, {TypeOf(uint32(0)), ""}, {TypeOf(uint64(0)), ""}, {TypeOf(uintptr(0)), ""}, {TypeOf(float32(0)), ""}, {TypeOf(float64(0)), ""}, {TypeOf(complex64(0)), ""}, {TypeOf(complex128(0)), ""}, {TypeOf(byte(0)), ""}, {TypeOf(rune(0)), ""}, {TypeOf([]byte(nil)), ""}, {TypeOf([]rune(nil)), ""}, {TypeOf(string("")), ""}, {TypeOf((*interface{})(nil)).Elem(), ""}, {TypeOf((*byte)(nil)), ""}, {TypeOf((*rune)(nil)), ""}, {TypeOf((*int64)(nil)), ""}, {TypeOf(map[string]int{}), ""}, {TypeOf((*error)(nil)).Elem(), ""}, {TypeOf((*Point)(nil)), ""}, {TypeOf((*Point)(nil)).Elem(), "internal/reflectlite_test"}, } for _, test := range tests { if path := test.t.PkgPath(); path != test.path { t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path) } } } func noAlloc(t *testing.T, n int, f func(int)) { if testing.Short() { t.Skip("skipping malloc count in short mode") } if runtime.GOMAXPROCS(0) > 1 { t.Skip("skipping; GOMAXPROCS>1") } i := -1 allocs := testing.AllocsPerRun(n, func() { f(i) i++ }) if allocs > 0 { t.Errorf("%d iterations: got %v mallocs, want 0", n, allocs) } } func TestAllocations(t *testing.T) { noAlloc(t, 100, func(j int) { var i interface{} var v Value // We can uncomment this when compiler escape analysis // is good enough to see that the integer assigned to i // does not escape and therefore need not be allocated. // // i = 42 + j // v = ValueOf(i) // if int(v.Int()) != 42+j { // panic("wrong int") // } i = func(j int) int { return j } v = ValueOf(i) if ToInterface(v).(func(int) int)(j) != j { panic("wrong result") } }) } func TestSetPanic(t *testing.T) { ok := func(f func()) { f() } bad := shouldPanic clear := func(v Value) { v.Set(Zero(v.Type())) } type t0 struct { W int } type t1 struct { Y int t0 } type T2 struct { Z int namedT0 t0 } type T struct { X int t1 T2 NamedT1 t1 NamedT2 T2 namedT1 t1 namedT2 T2 } // not addressable v := ValueOf(T{}) bad(func() { clear(Field(v, 0)) }) // .X bad(func() { clear(Field(v, 1)) }) // .t1 bad(func() { clear(Field(Field(v, 1), 0)) }) // .t1.Y bad(func() { clear(Field(Field(v, 1), 1)) }) // .t1.t0 bad(func() { clear(Field(Field(Field(v, 1), 1), 0)) }) // .t1.t0.W bad(func() { clear(Field(v, 2)) }) // .T2 bad(func() { clear(Field(Field(v, 2), 0)) }) // .T2.Z bad(func() { clear(Field(Field(v, 2), 1)) }) // .T2.namedT0 bad(func() { clear(Field(Field(Field(v, 2), 1), 0)) }) // .T2.namedT0.W bad(func() { clear(Field(v, 3)) }) // .NamedT1 bad(func() { clear(Field(Field(v, 3), 0)) }) // .NamedT1.Y bad(func() { clear(Field(Field(v, 3), 1)) }) // .NamedT1.t0 bad(func() { clear(Field(Field(Field(v, 3), 1), 0)) }) // .NamedT1.t0.W bad(func() { clear(Field(v, 4)) }) // .NamedT2 bad(func() { clear(Field(Field(v, 4), 0)) }) // .NamedT2.Z bad(func() { clear(Field(Field(v, 4), 1)) }) // .NamedT2.namedT0 bad(func() { clear(Field(Field(Field(v, 4), 1), 0)) }) // .NamedT2.namedT0.W bad(func() { clear(Field(v, 5)) }) // .namedT1 bad(func() { clear(Field(Field(v, 5), 0)) }) // .namedT1.Y bad(func() { clear(Field(Field(v, 5), 1)) }) // .namedT1.t0 bad(func() { clear(Field(Field(Field(v, 5), 1), 0)) }) // .namedT1.t0.W bad(func() { clear(Field(v, 6)) }) // .namedT2 bad(func() { clear(Field(Field(v, 6), 0)) }) // .namedT2.Z bad(func() { clear(Field(Field(v, 6), 1)) }) // .namedT2.namedT0 bad(func() { clear(Field(Field(Field(v, 6), 1), 0)) }) // .namedT2.namedT0.W // addressable v = ValueOf(&T{}).Elem() ok(func() { clear(Field(v, 0)) }) // .X bad(func() { clear(Field(v, 1)) }) // .t1 ok(func() { clear(Field(Field(v, 1), 0)) }) // .t1.Y bad(func() { clear(Field(Field(v, 1), 1)) }) // .t1.t0 ok(func() { clear(Field(Field(Field(v, 1), 1), 0)) }) // .t1.t0.W ok(func() { clear(Field(v, 2)) }) // .T2 ok(func() { clear(Field(Field(v, 2), 0)) }) // .T2.Z bad(func() { clear(Field(Field(v, 2), 1)) }) // .T2.namedT0 bad(func() { clear(Field(Field(Field(v, 2), 1), 0)) }) // .T2.namedT0.W ok(func() { clear(Field(v, 3)) }) // .NamedT1 ok(func() { clear(Field(Field(v, 3), 0)) }) // .NamedT1.Y bad(func() { clear(Field(Field(v, 3), 1)) }) // .NamedT1.t0 ok(func() { clear(Field(Field(Field(v, 3), 1), 0)) }) // .NamedT1.t0.W ok(func() { clear(Field(v, 4)) }) // .NamedT2 ok(func() { clear(Field(Field(v, 4), 0)) }) // .NamedT2.Z bad(func() { clear(Field(Field(v, 4), 1)) }) // .NamedT2.namedT0 bad(func() { clear(Field(Field(Field(v, 4), 1), 0)) }) // .NamedT2.namedT0.W bad(func() { clear(Field(v, 5)) }) // .namedT1 bad(func() { clear(Field(Field(v, 5), 0)) }) // .namedT1.Y bad(func() { clear(Field(Field(v, 5), 1)) }) // .namedT1.t0 bad(func() { clear(Field(Field(Field(v, 5), 1), 0)) }) // .namedT1.t0.W bad(func() { clear(Field(v, 6)) }) // .namedT2 bad(func() { clear(Field(Field(v, 6), 0)) }) // .namedT2.Z bad(func() { clear(Field(Field(v, 6), 1)) }) // .namedT2.namedT0 bad(func() { clear(Field(Field(Field(v, 6), 1), 0)) }) // .namedT2.namedT0.W } func shouldPanic(f func()) { defer func() { if recover() == nil { panic("did not panic") } }() f() } type S struct { i1 int64 i2 int64 } func TestBigZero(t *testing.T) { const size = 1 << 10 var v [size]byte z := ToInterface(Zero(ValueOf(v).Type())).([size]byte) for i := 0; i < size; i++ { if z[i] != 0 { t.Fatalf("Zero object not all zero, index %d", i) } } } func TestInvalid(t *testing.T) { // Used to have inconsistency between IsValid() and Kind() != Invalid. type T struct{ v interface{} } v := Field(ValueOf(T{}), 0) if v.IsValid() != true || v.Kind() != Interface { t.Errorf("field: IsValid=%v, Kind=%v, want true, Interface", v.IsValid(), v.Kind()) } v = v.Elem() if v.IsValid() != false || v.Kind() != Invalid { t.Errorf("field elem: IsValid=%v, Kind=%v, want false, Invalid", v.IsValid(), v.Kind()) } } type TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678 int type nameTest struct { v interface{} want string } var nameTests = []nameTest{ {(*int32)(nil), "int32"}, {(*D1)(nil), "D1"}, {(*[]D1)(nil), ""}, {(*chan D1)(nil), ""}, {(*func() D1)(nil), ""}, {(*<-chan D1)(nil), ""}, {(*chan<- D1)(nil), ""}, {(*interface{})(nil), ""}, {(*interface { F() })(nil), ""}, {(*TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678)(nil), "TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678"}, } func TestNames(t *testing.T) { for _, test := range nameTests { typ := TypeOf(test.v).Elem() if got := typ.Name(); got != test.want { t.Errorf("%v Name()=%q, want %q", typ, got, test.want) } } } // TestUnaddressableField tests that the reflect package will not allow // a type from another package to be used as a named type with an // unexported field. // // This ensures that unexported fields cannot be modified by other packages. func TestUnaddressableField(t *testing.T) { var b Buffer // type defined in reflect, a different package var localBuffer struct { buf []byte } lv := ValueOf(&localBuffer).Elem() rv := ValueOf(b) shouldPanic(func() { lv.Set(rv) }) } type Tint int type Tint2 = Tint type Talias1 struct { byte uint8 int int32 rune } type Talias2 struct { Tint Tint2 } func TestAliasNames(t *testing.T) { t1 := Talias1{byte: 1, uint8: 2, int: 3, int32: 4, rune: 5} out := fmt.Sprintf("%#v", t1) want := "reflectlite_test.Talias1{byte:0x1, uint8:0x2, int:3, int32:4, rune:5}" if out != want { t.Errorf("Talias1 print:\nhave: %s\nwant: %s", out, want) } t2 := Talias2{Tint: 1, Tint2: 2} out = fmt.Sprintf("%#v", t2) want = "reflectlite_test.Talias2{Tint:1, Tint2:2}" if out != want { t.Errorf("Talias2 print:\nhave: %s\nwant: %s", out, want) } }