aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/reflect/all_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/all_test.go')
-rw-r--r--libgo/go/reflect/all_test.go908
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)
+ }
+}