diff options
Diffstat (limited to 'libgo/go/reflect/all_test.go')
-rw-r--r-- | libgo/go/reflect/all_test.go | 908 |
1 files changed, 832 insertions, 76 deletions
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index b8e7cd8..7045e44 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -21,6 +21,8 @@ import ( "sync" "testing" "time" + "unicode" + "unicode/utf8" "unsafe" ) @@ -44,16 +46,12 @@ type pair struct { s string } -func isDigit(c uint8) bool { return '0' <= c && c <= '9' } - func assert(t *testing.T, s, want string) { if s != want { t.Errorf("have %#q want %#q", s, want) } } -func typestring(i interface{}) string { return TypeOf(i).String() } - var typeTests = []pair{ {struct{ x int }{}, "int"}, {struct{ x int8 }{}, "int8"}, @@ -1891,32 +1889,6 @@ type Tbigp [2]uintptr func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) } -// Again, with an unexported method. - -type tsmallv byte - -func (v tsmallv) m(x int, b byte) (byte, int) { return b, x + int(v) } - -type tsmallp byte - -func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x + int(*p) } - -type twordv uintptr - -func (v twordv) m(x int, b byte) (byte, int) { return b, x + int(v) } - -type twordp uintptr - -func (p *twordp) m(x int, b byte) (byte, int) { return b, x + int(*p) } - -type tbigv [2]uintptr - -func (v tbigv) m(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) } - -type tbigp [2]uintptr - -func (p *tbigp) m(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) } - type tinter interface { m(int, byte) (byte, int) } @@ -1960,7 +1932,6 @@ func TestMethod5(t *testing.T) { } var TinterType = TypeOf(new(Tinter)).Elem() - var tinterType = TypeOf(new(tinter)).Elem() CheckI := func(name string, i interface{}, inc int) { v := ValueOf(i) @@ -2002,39 +1973,6 @@ func TestMethod5(t *testing.T) { CheckI("t1", t1, 40) CheckI("&t1", &t1, 40) - methodShouldPanic := func(name string, i interface{}) { - v := ValueOf(i) - m := v.Method(0) - shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) }) - shouldPanic(func() { m.Interface() }) - - v = v.Convert(tinterType) - m = v.Method(0) - shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) }) - shouldPanic(func() { m.Interface() }) - } - - _sv := tsmallv(1) - methodShouldPanic("_sv", _sv) - methodShouldPanic("&_sv", &_sv) - - _sp := tsmallp(2) - methodShouldPanic("&_sp", &_sp) - - _wv := twordv(3) - methodShouldPanic("_wv", _wv) - methodShouldPanic("&_wv", &_wv) - - _wp := twordp(4) - methodShouldPanic("&_wp", &_wp) - - _bv := tbigv([2]uintptr{5, 6}) - methodShouldPanic("_bv", _bv) - methodShouldPanic("&_bv", &_bv) - - _bp := tbigp([2]uintptr{7, 8}) - methodShouldPanic("&_bp", &_bp) - var tnil Tinter vnil := ValueOf(&tnil).Elem() shouldPanic(func() { vnil.Method(0) }) @@ -2323,6 +2261,8 @@ func TestImportPath(t *testing.T) { {TypeOf((*int64)(nil)), ""}, {TypeOf(map[string]int{}), ""}, {TypeOf((*error)(nil)).Elem(), ""}, + {TypeOf((*Point)(nil)), ""}, + {TypeOf((*Point)(nil)).Elem(), "reflect_test"}, } for _, test := range tests { if path := test.t.PkgPath(); path != test.path { @@ -2331,6 +2271,33 @@ func TestImportPath(t *testing.T) { } } +func TestFieldPkgPath(t *testing.T) { + typ := TypeOf(struct { + Exported string + unexported string + OtherPkgFields + }{}) + for _, test := range []struct { + index []int + pkgPath string + anonymous bool + }{ + {[]int{0}, "", false}, // Exported + {[]int{1}, "reflect_test", false}, // unexported + {[]int{2}, "", true}, // OtherPkgFields + {[]int{2, 0}, "", false}, // OtherExported + {[]int{2, 1}, "reflect", false}, // otherUnexported + } { + f := typ.FieldByIndex(test.index) + if got, want := f.PkgPath, test.pkgPath; got != want { + t.Errorf("Field(%d).PkgPath = %q, want %q", test.index, got, want) + } + if got, want := f.Anonymous, test.anonymous; got != want { + t.Errorf("Field(%d).Anonymous = %v, want %v", test.index, got, want) + } + } +} + func TestVariadicType(t *testing.T) { // Test example from Type documentation. var f func(x int, y ...float64) @@ -2363,14 +2330,14 @@ type outer struct { inner } -func (*inner) m() {} -func (*outer) m() {} +func (*inner) M() {} +func (*outer) M() {} func TestNestedMethods(t *testing.T) { t.Skip("fails on gccgo due to function wrappers") typ := TypeOf((*outer)(nil)) - if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() { - t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m) + if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).M).Pointer() { + t.Errorf("Wrong method table for outer: (M=%p)", (*outer).M) for i := 0; i < typ.NumMethod(); i++ { m := typ.Method(i) t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) @@ -2378,6 +2345,25 @@ func TestNestedMethods(t *testing.T) { } } +type unexp struct{} + +func (*unexp) f() (int32, int8) { return 7, 7 } +func (*unexp) g() (int64, int8) { return 8, 8 } + +type unexpI interface { + f() (int32, int8) +} + +var unexpi unexpI = new(unexp) + +func TestUnexportedMethods(t *testing.T) { + typ := TypeOf(unexpi) + + if got := typ.NumMethod(); got != 0 { + t.Errorf("NumMethod=%d, want 0 satisfied methods", got) + } +} + type InnerInt struct { X int } @@ -2419,6 +2405,17 @@ func TestEmbeddedMethods(t *testing.T) { } } +type FuncDDD func(...interface{}) error + +func (f FuncDDD) M() {} + +func TestNumMethodOnDDD(t *testing.T) { + rv := ValueOf((FuncDDD)(nil)) + if n := rv.NumMethod(); n != 1 { + t.Fatalf("NumMethod()=%d, want 1", n) + } +} + func TestPtrTo(t *testing.T) { var i int @@ -2861,12 +2858,11 @@ func TestUnexported(t *testing.T) { isValid(v.Elem().Field(1)) isValid(v.Elem().FieldByName("x")) isValid(v.Elem().FieldByName("y")) - isValid(v.Type().Method(0).Func) shouldPanic(func() { v.Elem().Field(0).Interface() }) shouldPanic(func() { v.Elem().Field(1).Interface() }) shouldPanic(func() { v.Elem().FieldByName("x").Interface() }) shouldPanic(func() { v.Elem().FieldByName("y").Interface() }) - shouldPanic(func() { v.Type().Method(0).Func.Interface() }) + shouldPanic(func() { v.Type().Method(0) }) } func TestSetPanic(t *testing.T) { @@ -3846,6 +3842,9 @@ func TestSliceOf(t *testing.T) { // check construction and use of type not in binary type T int st := SliceOf(TypeOf(T(1))) + if got, want := st.String(), "[]reflect_test.T"; got != want { + t.Errorf("SliceOf(T(1)).String()=%q, want %q", got, want) + } v := MakeSlice(st, 10, 10) runtime.GC() for i := 0; i < v.Len(); i++ { @@ -3910,6 +3909,591 @@ func TestSliceOfGC(t *testing.T) { } } +func TestStructOf(t *testing.T) { + // check construction and use of type not in binary + fields := []StructField{ + StructField{ + Name: "S", + Tag: "s", + Type: TypeOf(""), + }, + StructField{ + Name: "X", + Tag: "x", + Type: TypeOf(byte(0)), + }, + StructField{ + Name: "Y", + Type: TypeOf(uint64(0)), + }, + StructField{ + Name: "Z", + Type: TypeOf([3]uint16{}), + }, + } + + st := StructOf(fields) + v := New(st).Elem() + runtime.GC() + v.FieldByName("X").Set(ValueOf(byte(2))) + v.FieldByIndex([]int{1}).Set(ValueOf(byte(1))) + runtime.GC() + + s := fmt.Sprint(v.Interface()) + want := `{ 1 0 [0 0 0]}` + if s != want { + t.Errorf("constructed struct = %s, want %s", s, want) + } + const stStr = `struct { S string "s"; X uint8 "x"; Y uint64; Z [3]uint16 }` + if got, want := st.String(), stStr; got != want { + t.Errorf("StructOf(fields).String()=%q, want %q", got, want) + } + + // check the size, alignment and field offsets + stt := TypeOf(struct { + String string + X byte + Y uint64 + Z [3]uint16 + }{}) + if st.Size() != stt.Size() { + t.Errorf("constructed struct size = %v, want %v", st.Size(), stt.Size()) + } + if st.Align() != stt.Align() { + t.Errorf("constructed struct align = %v, want %v", st.Align(), stt.Align()) + } + if st.FieldAlign() != stt.FieldAlign() { + t.Errorf("constructed struct field align = %v, want %v", st.FieldAlign(), stt.FieldAlign()) + } + for i := 0; i < st.NumField(); i++ { + o1 := st.Field(i).Offset + o2 := stt.Field(i).Offset + if o1 != o2 { + t.Errorf("constructed struct field %v offset = %v, want %v", i, o1, o2) + } + } + + // check duplicate names + shouldPanic(func() { + StructOf([]StructField{ + StructField{Name: "string", Type: TypeOf("")}, + StructField{Name: "string", Type: TypeOf("")}, + }) + }) + shouldPanic(func() { + StructOf([]StructField{ + StructField{Type: TypeOf("")}, + StructField{Name: "string", Type: TypeOf("")}, + }) + }) + shouldPanic(func() { + StructOf([]StructField{ + StructField{Type: TypeOf("")}, + StructField{Type: TypeOf("")}, + }) + }) + // check that type already in binary is found + checkSameType(t, Zero(StructOf(fields[2:3])).Interface(), struct{ Y uint64 }{}) +} + +func TestStructOfExportRules(t *testing.T) { + type S1 struct{} + type s2 struct{} + type ΦType struct{} + type φType struct{} + + testPanic := func(i int, mustPanic bool, f func()) { + defer func() { + err := recover() + if err == nil && mustPanic { + t.Errorf("test-%d did not panic", i) + } + if err != nil && !mustPanic { + t.Errorf("test-%d panicked: %v\n", i, err) + } + }() + f() + } + + for i, test := range []struct { + field StructField + mustPanic bool + exported bool + }{ + { + field: StructField{Name: "", Type: TypeOf(S1{})}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "", Type: TypeOf((*S1)(nil))}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "", Type: TypeOf(s2{})}, + mustPanic: false, + exported: false, + }, + { + field: StructField{Name: "", Type: TypeOf((*s2)(nil))}, + mustPanic: false, + exported: false, + }, + { + field: StructField{Name: "", Type: TypeOf(S1{}), PkgPath: "other/pkg"}, + mustPanic: true, + exported: true, + }, + { + field: StructField{Name: "", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"}, + mustPanic: true, + exported: true, + }, + { + field: StructField{Name: "", Type: TypeOf(s2{}), PkgPath: "other/pkg"}, + mustPanic: true, + exported: false, + }, + { + field: StructField{Name: "", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"}, + mustPanic: true, + exported: false, + }, + { + field: StructField{Name: "S", Type: TypeOf(S1{})}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "S", Type: TypeOf((*S1)(nil))}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "S", Type: TypeOf(s2{})}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "S", Type: TypeOf((*s2)(nil))}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "s", Type: TypeOf(S1{})}, + mustPanic: true, + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf((*S1)(nil))}, + mustPanic: true, + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf(s2{})}, + mustPanic: true, + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf((*s2)(nil))}, + mustPanic: true, + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf(S1{}), PkgPath: "other/pkg"}, + mustPanic: true, // TODO(sbinet): creating a name with a package path + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"}, + mustPanic: true, // TODO(sbinet): creating a name with a package path + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf(s2{}), PkgPath: "other/pkg"}, + mustPanic: true, // TODO(sbinet): creating a name with a package path + exported: false, + }, + { + field: StructField{Name: "s", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"}, + mustPanic: true, // TODO(sbinet): creating a name with a package path + exported: false, + }, + { + field: StructField{Name: "", Type: TypeOf(ΦType{})}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "", Type: TypeOf(φType{})}, + mustPanic: false, + exported: false, + }, + { + field: StructField{Name: "Φ", Type: TypeOf(0)}, + mustPanic: false, + exported: true, + }, + { + field: StructField{Name: "φ", Type: TypeOf(0)}, + mustPanic: false, + exported: false, + }, + } { + testPanic(i, test.mustPanic, func() { + typ := StructOf([]StructField{test.field}) + if typ == nil { + t.Errorf("test-%d: error creating struct type", i) + return + } + field := typ.Field(0) + n := field.Name + if n == "" { + n = field.Type.Name() + } + exported := isExported(n) + if exported != test.exported { + t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported) + } + }) + } +} + +// isExported reports whether name is an exported Go symbol +// (that is, whether it begins with an upper-case letter). +// +func isExported(name string) bool { + ch, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(ch) +} + +func TestStructOfGC(t *testing.T) { + type T *uintptr + tt := TypeOf(T(nil)) + fields := []StructField{ + {Name: "X", Type: tt}, + {Name: "Y", Type: tt}, + } + st := StructOf(fields) + + const n = 10000 + var x []interface{} + for i := 0; i < n; i++ { + v := New(st).Elem() + for j := 0; j < v.NumField(); j++ { + p := new(uintptr) + *p = uintptr(i*n + j) + v.Field(j).Set(ValueOf(p).Convert(tt)) + } + x = append(x, v.Interface()) + } + runtime.GC() + + for i, xi := range x { + v := ValueOf(xi) + for j := 0; j < v.NumField(); j++ { + k := v.Field(j).Elem().Interface() + if k != uintptr(i*n+j) { + t.Errorf("lost x[%d].%c = %d, want %d", i, "XY"[j], k, i*n+j) + } + } + } +} + +func TestStructOfAlg(t *testing.T) { + st := StructOf([]StructField{{Name: "X", Tag: "x", Type: TypeOf(int(0))}}) + v1 := New(st).Elem() + v2 := New(st).Elem() + if !DeepEqual(v1.Interface(), v1.Interface()) { + t.Errorf("constructed struct %v not equal to itself", v1.Interface()) + } + v1.FieldByName("X").Set(ValueOf(int(1))) + if i1, i2 := v1.Interface(), v2.Interface(); DeepEqual(i1, i2) { + t.Errorf("constructed structs %v and %v should not be equal", i1, i2) + } + + st = StructOf([]StructField{{Name: "X", Tag: "x", Type: TypeOf([]int(nil))}}) + v1 = New(st).Elem() + shouldPanic(func() { _ = v1.Interface() == v1.Interface() }) +} + +func TestStructOfGenericAlg(t *testing.T) { + st1 := StructOf([]StructField{ + {Name: "X", Tag: "x", Type: TypeOf(int64(0))}, + {Name: "Y", Type: TypeOf(string(""))}, + }) + st := StructOf([]StructField{ + {Name: "S0", Type: st1}, + {Name: "S1", Type: st1}, + }) + + for _, table := range []struct { + rt Type + idx []int + }{ + { + rt: st, + idx: []int{0, 1}, + }, + { + rt: st1, + idx: []int{1}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf([0]int{})}, + {Name: "YY", Type: TypeOf("")}, + }, + ), + idx: []int{1}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf([0]int{})}, + {Name: "YY", Type: TypeOf("")}, + {Name: "ZZ", Type: TypeOf([2]int{})}, + }, + ), + idx: []int{1}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf([1]int{})}, + {Name: "YY", Type: TypeOf("")}, + }, + ), + idx: []int{1}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf([1]int{})}, + {Name: "YY", Type: TypeOf("")}, + {Name: "ZZ", Type: TypeOf([1]int{})}, + }, + ), + idx: []int{1}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf([2]int{})}, + {Name: "YY", Type: TypeOf("")}, + {Name: "ZZ", Type: TypeOf([2]int{})}, + }, + ), + idx: []int{1}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf(int64(0))}, + {Name: "YY", Type: TypeOf(byte(0))}, + {Name: "ZZ", Type: TypeOf("")}, + }, + ), + idx: []int{2}, + }, + { + rt: StructOf( + []StructField{ + {Name: "XX", Type: TypeOf(int64(0))}, + {Name: "YY", Type: TypeOf(int64(0))}, + {Name: "ZZ", Type: TypeOf("")}, + {Name: "AA", Type: TypeOf([1]int64{})}, + }, + ), + idx: []int{2}, + }, + } { + v1 := New(table.rt).Elem() + v2 := New(table.rt).Elem() + + if !DeepEqual(v1.Interface(), v1.Interface()) { + t.Errorf("constructed struct %v not equal to itself", v1.Interface()) + } + + v1.FieldByIndex(table.idx).Set(ValueOf("abc")) + v2.FieldByIndex(table.idx).Set(ValueOf("def")) + if i1, i2 := v1.Interface(), v2.Interface(); DeepEqual(i1, i2) { + t.Errorf("constructed structs %v and %v should not be equal", i1, i2) + } + + abc := "abc" + v1.FieldByIndex(table.idx).Set(ValueOf(abc)) + val := "+" + abc + "-" + v2.FieldByIndex(table.idx).Set(ValueOf(val[1:4])) + if i1, i2 := v1.Interface(), v2.Interface(); !DeepEqual(i1, i2) { + t.Errorf("constructed structs %v and %v should be equal", i1, i2) + } + + // Test hash + m := MakeMap(MapOf(table.rt, TypeOf(int(0)))) + m.SetMapIndex(v1, ValueOf(1)) + if i1, i2 := v1.Interface(), v2.Interface(); !m.MapIndex(v2).IsValid() { + t.Errorf("constructed structs %#v and %#v have different hashes", i1, i2) + } + + v2.FieldByIndex(table.idx).Set(ValueOf("abc")) + if i1, i2 := v1.Interface(), v2.Interface(); !DeepEqual(i1, i2) { + t.Errorf("constructed structs %v and %v should be equal", i1, i2) + } + + if i1, i2 := v1.Interface(), v2.Interface(); !m.MapIndex(v2).IsValid() { + t.Errorf("constructed structs %v and %v have different hashes", i1, i2) + } + } +} + +/* +gccgo does not use the same directiface settings as gc. + +func TestStructOfDirectIface(t *testing.T) { + { + type T struct{ X [1]*byte } + i1 := Zero(TypeOf(T{})).Interface() + v1 := ValueOf(&i1).Elem() + p1 := v1.InterfaceData()[1] + + i2 := Zero(StructOf([]StructField{ + { + Name: "X", + Type: ArrayOf(1, TypeOf((*int8)(nil))), + }, + })).Interface() + v2 := ValueOf(&i2).Elem() + p2 := v2.InterfaceData()[1] + + if p1 != 0 { + t.Errorf("got p1=%v. want=%v", p1, nil) + } + + if p2 != 0 { + t.Errorf("got p2=%v. want=%v", p2, nil) + } + } + { + type T struct{ X [0]*byte } + i1 := Zero(TypeOf(T{})).Interface() + v1 := ValueOf(&i1).Elem() + p1 := v1.InterfaceData()[1] + + i2 := Zero(StructOf([]StructField{ + { + Name: "X", + Type: ArrayOf(0, TypeOf((*int8)(nil))), + }, + })).Interface() + v2 := ValueOf(&i2).Elem() + p2 := v2.InterfaceData()[1] + + if p1 == 0 { + t.Errorf("got p1=%v. want=not-%v", p1, nil) + } + + if p2 == 0 { + t.Errorf("got p2=%v. want=not-%v", p2, nil) + } + } +} +*/ + +type StructI int + +func (i StructI) Get() int { return int(i) } + +type StructIPtr int + +func (i *StructIPtr) Get() int { return int(*i) } + +/* +gccgo does not yet support StructOf with methods. + +func TestStructOfWithInterface(t *testing.T) { + const want = 42 + type Iface interface { + Get() int + } + for i, table := range []struct { + typ Type + val Value + impl bool + }{ + { + typ: TypeOf(StructI(want)), + val: ValueOf(StructI(want)), + impl: true, + }, + { + typ: PtrTo(TypeOf(StructI(want))), + val: ValueOf(func() interface{} { + v := StructI(want) + return &v + }()), + impl: true, + }, + { + typ: PtrTo(TypeOf(StructIPtr(want))), + val: ValueOf(func() interface{} { + v := StructIPtr(want) + return &v + }()), + impl: true, + }, + { + typ: TypeOf(StructIPtr(want)), + val: ValueOf(StructIPtr(want)), + impl: false, + }, + // { + // typ: TypeOf((*Iface)(nil)).Elem(), // FIXME(sbinet): fix method.ifn/tfn + // val: ValueOf(StructI(want)), + // impl: true, + // }, + } { + rt := StructOf( + []StructField{ + { + Name: "", + PkgPath: "", + Type: table.typ, + }, + }, + ) + rv := New(rt).Elem() + rv.Field(0).Set(table.val) + + if _, ok := rv.Interface().(Iface); ok != table.impl { + if table.impl { + t.Errorf("test-%d: type=%v fails to implement Iface.\n", i, table.typ) + } else { + t.Errorf("test-%d: type=%v should NOT implement Iface\n", i, table.typ) + } + continue + } + + if !table.impl { + continue + } + + v := rv.Interface().(Iface).Get() + if v != want { + t.Errorf("test-%d: x.Get()=%v. want=%v\n", i, v, want) + } + + fct := rv.MethodByName("Get") + out := fct.Call(nil) + if !DeepEqual(out[0].Interface(), want) { + t.Errorf("test-%d: x.Get()=%v. want=%v\n", i, out[0].Interface(), want) + } + } +} +*/ + func TestChanOf(t *testing.T) { // check construction and use of type not in binary type T string @@ -4116,7 +4700,7 @@ func TestFuncOf(t *testing.T) { if len(args) != 1 { t.Errorf("args == %v, want exactly one arg", args) } else if args[0].Type() != TypeOf(K("")) { - t.Errorf("args[0] is type %v, want %v", args[0].Type, TypeOf(K(""))) + t.Errorf("args[0] is type %v, want %v", args[0].Type(), TypeOf(K(""))) } else if args[0].String() != "gopher" { t.Errorf("args[0] = %q, want %q", args[0].String(), "gopher") } @@ -4128,7 +4712,7 @@ func TestFuncOf(t *testing.T) { if len(outs) != 1 { t.Fatalf("v.Call returned %v, want exactly one result", outs) } else if outs[0].Type() != TypeOf(V(0)) { - t.Fatalf("c.Call[0] is type %v, want %v", outs[0].Type, TypeOf(V(0))) + t.Fatalf("c.Call[0] is type %v, want %v", outs[0].Type(), TypeOf(V(0))) } f := outs[0].Float() if f != 3.14 { @@ -4479,7 +5063,7 @@ func TestFieldByIndexNil(t *testing.T) { // off the stack into the frame will store an *Inner there, and then if a garbage collection // happens to scan that argument frame before it is discarded, it will scan the *Inner // memory as if it were an *Outer. If the two have different memory layouts, the -// collection will intepret the memory incorrectly. +// collection will interpret the memory incorrectly. // // One such possible incorrect interpretation is to treat two arbitrary memory words // (Inner.P1 and Inner.P2 below) as an interface (Outer.R below). Because interpreting @@ -4555,7 +5139,7 @@ func useStack(n int) { type Impl struct{} -func (Impl) f() {} +func (Impl) F() {} func TestValueString(t *testing.T) { rv := ValueOf(Impl{}) @@ -4589,6 +5173,41 @@ func TestLargeGCProg(t *testing.T) { fv.Call([]Value{ValueOf([256]*byte{})}) } +func fieldIndexRecover(t Type, i int) (recovered interface{}) { + defer func() { + recovered = recover() + }() + + t.Field(i) + return +} + +// Issue 15046. +func TestTypeFieldOutOfRangePanic(t *testing.T) { + typ := TypeOf(struct{ X int }{10}) + testIndices := [...]struct { + i int + mustPanic bool + }{ + 0: {-2, true}, + 1: {0, false}, + 2: {1, true}, + 3: {1 << 10, true}, + } + for i, tt := range testIndices { + recoveredErr := fieldIndexRecover(typ, tt.i) + if tt.mustPanic { + if recoveredErr == nil { + t.Errorf("#%d: fieldIndex %d expected to panic", i, tt.i) + } + } else { + if recoveredErr != nil { + t.Errorf("#%d: got err=%v, expected no panic", i, recoveredErr) + } + } + } +} + // Issue 9179. func TestCallGC(t *testing.T) { f := func(a, b, c, d, e string) { @@ -4716,7 +5335,7 @@ func init() { 2 * PtrSize, []byte{1}, []byte{1}, - // Note: this one is tricky, as the receiver is not a pointer. But we + // Note: this one is tricky, as the receiver is not a pointer. But we // pass the receiver by reference to the autogenerated pointer-receiver // version of the function. }) @@ -4768,6 +5387,9 @@ func verifyGCBitsSlice(t *testing.T, typ Type, cap int, bits []byte) { for len(bits) > 2 && bits[len(bits)-1] == 0 { bits = bits[:len(bits)-1] } + if len(bits) == 2 && bits[0] == 0 && bits[1] == 0 { + bits = bits[:0] + } if !bytes.Equal(heapBits, bits) { t.Errorf("heapBits incorrect for make(%v, 0, %v)\nhave %v\nwant %v", typ, cap, heapBits, bits) } @@ -5027,6 +5649,140 @@ func TestChanAlloc(t *testing.T) { t.Errorf("allocs per chan send/recv: want 1 got %f", allocs) } // Note: there is one allocation in reflect.recv which seems to be - // a limitation of escape analysis. If that is ever fixed the + // a limitation of escape analysis. If that is ever fixed the // allocs < 0.5 condition will trigger and this test should be fixed. } + +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) + } + } +} + +/* +gccgo doesn't really record whether a type is exported. +It's not in the reflect API anyhow. + +func TestExported(t *testing.T) { + type ΦExported struct{} + type φUnexported struct{} + type BigP *big + type P int + type p *P + type P2 p + type p3 p + + type exportTest struct { + v interface{} + want bool + } + exportTests := []exportTest{ + {D1{}, true}, + {(*D1)(nil), true}, + {big{}, false}, + {(*big)(nil), false}, + {(BigP)(nil), true}, + {(*BigP)(nil), true}, + {ΦExported{}, true}, + {φUnexported{}, false}, + {P(0), true}, + {(p)(nil), false}, + {(P2)(nil), true}, + {(p3)(nil), false}, + } + + for i, test := range exportTests { + typ := TypeOf(test.v) + if got := IsExported(typ); got != test.want { + t.Errorf("%d: %s exported=%v, want %v", i, typ.Name(), got, test.want) + } + } +} +*/ + +type embed struct { + EmbedWithUnexpMeth +} + +/* +func TestNameBytesAreAligned(t *testing.T) { + typ := TypeOf(embed{}) + b := FirstMethodNameBytes(typ) + v := uintptr(unsafe.Pointer(b)) + if v%unsafe.Alignof((*byte)(nil)) != 0 { + t.Errorf("reflect.name.bytes pointer is not aligned: %x", v) + } +} +*/ + +func TestTypeStrings(t *testing.T) { + type stringTest struct { + typ Type + want string + } + stringTests := []stringTest{ + {TypeOf(func(int) {}), "func(int)"}, + {FuncOf([]Type{TypeOf(int(0))}, nil, false), "func(int)"}, + {TypeOf(XM{}), "reflect_test.XM"}, + {TypeOf(new(XM)), "*reflect_test.XM"}, + {TypeOf(new(XM).String), "func() string"}, + {TypeOf(new(XM)).Method(0).Type, "func(*reflect_test.XM) string"}, + } + + for i, test := range stringTests { + if got, want := test.typ.String(), test.want; got != want { + t.Errorf("type %d String()=%q, want %q", i, got, want) + } + } +} + +/* +gccgo does not have resolveReflectName. + +func TestOffsetLock(t *testing.T) { + var wg sync.WaitGroup + for i := 0; i < 4; i++ { + i := i + wg.Add(1) + go func() { + for j := 0; j < 50; j++ { + ResolveReflectName(fmt.Sprintf("OffsetLockName:%d:%d", i, j)) + } + wg.Done() + }() + } + wg.Wait() +} +*/ + +func BenchmarkNew(b *testing.B) { + v := TypeOf(XM{}) + for i := 0; i < b.N; i++ { + New(v) + } +} |