summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gofrontend/libgo/go/reflect/all_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'llgo/third_party/gofrontend/libgo/go/reflect/all_test.go')
-rw-r--r--llgo/third_party/gofrontend/libgo/go/reflect/all_test.go672
1 files changed, 647 insertions, 25 deletions
diff --git a/llgo/third_party/gofrontend/libgo/go/reflect/all_test.go b/llgo/third_party/gofrontend/libgo/go/reflect/all_test.go
index bda87867c74..33ee9ed83cc 100644
--- a/llgo/third_party/gofrontend/libgo/go/reflect/all_test.go
+++ b/llgo/third_party/gofrontend/libgo/go/reflect/all_test.go
@@ -15,6 +15,7 @@ import (
. "reflect"
"runtime"
"sort"
+ "strconv"
"strings"
"sync"
"testing"
@@ -1052,6 +1053,11 @@ func TestChan(t *testing.T) {
ok = cv.TrySend(ValueOf(6))
if !ok {
t.Errorf("TrySend on empty chan failed")
+ select {
+ case x := <-c:
+ t.Errorf("TrySend failed but it did send %d", x)
+ default:
+ }
} else {
if i = <-c; i != 6 {
t.Errorf("TrySend 6, recv %d", i)
@@ -1376,7 +1382,7 @@ func selectWatcher() {
for {
time.Sleep(1 * time.Second)
selectWatch.Lock()
- if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second {
+ if selectWatch.info != nil && time.Since(selectWatch.now) > 10*time.Second {
fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info))
panic("select stuck")
}
@@ -1501,6 +1507,17 @@ func TestCallWithStruct(t *testing.T) {
}
}
+func BenchmarkCall(b *testing.B) {
+ fv := ValueOf(func(a, b string) {})
+ b.ReportAllocs()
+ b.RunParallel(func(pb *testing.PB) {
+ args := []Value{ValueOf("a"), ValueOf("b")}
+ for pb.Next() {
+ fv.Call(args)
+ }
+ })
+}
+
func TestMakeFunc(t *testing.T) {
f := dummy
fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
@@ -2726,6 +2743,8 @@ var tagGetTests = []struct {
{`protobuf:"PB(1,2)"`, `rotobuf`, ``},
{`protobuf:"PB(1,2)" json:"name"`, `json`, `name`},
{`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`},
+ {`k0:"values contain spaces" k1:"and\ttabs"`, "k0", "values contain spaces"},
+ {`k0:"values contain spaces" k1:"and\ttabs"`, "k1", "and\ttabs"},
}
func TestTagGet(t *testing.T) {
@@ -3377,26 +3396,243 @@ func checkSameType(t *testing.T, x, y interface{}) {
}
func TestArrayOf(t *testing.T) {
- // TODO(rsc): Finish ArrayOf and enable-test.
- t.Skip("ArrayOf is not finished (and not exported)")
-
// check construction and use of type not in binary
- type T int
- at := ArrayOf(10, TypeOf(T(1)))
- v := New(at).Elem()
- for i := 0; i < v.Len(); i++ {
- v.Index(i).Set(ValueOf(T(i)))
- }
- s := fmt.Sprint(v.Interface())
- want := "[0 1 2 3 4 5 6 7 8 9]"
- if s != want {
- t.Errorf("constructed array = %s, want %s", s, want)
+ for _, table := range []struct {
+ n int
+ value func(i int) interface{}
+ comparable bool
+ want string
+ }{
+ {
+ n: 0,
+ value: func(i int) interface{} { type Tint int; return Tint(i) },
+ comparable: true,
+ want: "[]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tint int; return Tint(i) },
+ comparable: true,
+ want: "[0 1 2 3 4 5 6 7 8 9]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tfloat float64; return Tfloat(i) },
+ comparable: true,
+ want: "[0 1 2 3 4 5 6 7 8 9]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tstring string; return Tstring(strconv.Itoa(i)) },
+ comparable: true,
+ want: "[0 1 2 3 4 5 6 7 8 9]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tstruct struct{ V int }; return Tstruct{i} },
+ comparable: true,
+ want: "[{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tint int; return []Tint{Tint(i)} },
+ comparable: false,
+ want: "[[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tint int; return [1]Tint{Tint(i)} },
+ comparable: true,
+ want: "[[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tstruct struct{ V [1]int }; return Tstruct{[1]int{i}} },
+ comparable: true,
+ want: "[{[0]} {[1]} {[2]} {[3]} {[4]} {[5]} {[6]} {[7]} {[8]} {[9]}]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type Tstruct struct{ V []int }; return Tstruct{[]int{i}} },
+ comparable: false,
+ want: "[{[0]} {[1]} {[2]} {[3]} {[4]} {[5]} {[6]} {[7]} {[8]} {[9]}]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} { type TstructUV struct{ U, V int }; return TstructUV{i, i} },
+ comparable: true,
+ want: "[{0 0} {1 1} {2 2} {3 3} {4 4} {5 5} {6 6} {7 7} {8 8} {9 9}]",
+ },
+ {
+ n: 10,
+ value: func(i int) interface{} {
+ type TstructUV struct {
+ U int
+ V float64
+ }
+ return TstructUV{i, float64(i)}
+ },
+ comparable: true,
+ want: "[{0 0} {1 1} {2 2} {3 3} {4 4} {5 5} {6 6} {7 7} {8 8} {9 9}]",
+ },
+ } {
+ at := ArrayOf(table.n, TypeOf(table.value(0)))
+ v := New(at).Elem()
+ vok := New(at).Elem()
+ vnot := New(at).Elem()
+ for i := 0; i < v.Len(); i++ {
+ v.Index(i).Set(ValueOf(table.value(i)))
+ vok.Index(i).Set(ValueOf(table.value(i)))
+ j := i
+ if i+1 == v.Len() {
+ j = i + 1
+ }
+ vnot.Index(i).Set(ValueOf(table.value(j))) // make it differ only by last element
+ }
+ s := fmt.Sprint(v.Interface())
+ if s != table.want {
+ t.Errorf("constructed array = %s, want %s", s, table.want)
+ }
+
+ if table.comparable != at.Comparable() {
+ t.Errorf("constructed array (%#v) is comparable=%v, want=%v", v.Interface(), at.Comparable(), table.comparable)
+ }
+ if table.comparable {
+ if table.n > 0 {
+ if DeepEqual(vnot.Interface(), v.Interface()) {
+ t.Errorf(
+ "arrays (%#v) compare ok (but should not)",
+ v.Interface(),
+ )
+ }
+ }
+ if !DeepEqual(vok.Interface(), v.Interface()) {
+ t.Errorf(
+ "arrays (%#v) compare NOT-ok (but should)",
+ v.Interface(),
+ )
+ }
+ }
}
// check that type already in binary is found
+ type T int
checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{})
}
+func TestArrayOfGC(t *testing.T) {
+ type T *uintptr
+ tt := TypeOf(T(nil))
+ const n = 100
+ var x []interface{}
+ for i := 0; i < n; i++ {
+ v := New(ArrayOf(n, tt)).Elem()
+ for j := 0; j < v.Len(); j++ {
+ p := new(uintptr)
+ *p = uintptr(i*n + j)
+ v.Index(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.Len(); j++ {
+ k := v.Index(j).Elem().Interface()
+ if k != uintptr(i*n+j) {
+ t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
+ }
+ }
+ }
+}
+
+func TestArrayOfAlg(t *testing.T) {
+ at := ArrayOf(6, TypeOf(byte(0)))
+ v1 := New(at).Elem()
+ v2 := New(at).Elem()
+ if v1.Interface() != v1.Interface() {
+ t.Errorf("constructed array %v not equal to itself", v1.Interface())
+ }
+ v1.Index(5).Set(ValueOf(byte(1)))
+ if i1, i2 := v1.Interface(), v2.Interface(); i1 == i2 {
+ t.Errorf("constructed arrays %v and %v should not be equal", i1, i2)
+ }
+
+ at = ArrayOf(6, TypeOf([]int(nil)))
+ v1 = New(at).Elem()
+ shouldPanic(func() { _ = v1.Interface() == v1.Interface() })
+}
+
+func TestArrayOfGenericAlg(t *testing.T) {
+ at1 := ArrayOf(5, TypeOf(string("")))
+ at := ArrayOf(6, at1)
+ v1 := New(at).Elem()
+ v2 := New(at).Elem()
+ if v1.Interface() != v1.Interface() {
+ t.Errorf("constructed array %v not equal to itself", v1.Interface())
+ }
+
+ v1.Index(0).Index(0).Set(ValueOf("abc"))
+ v2.Index(0).Index(0).Set(ValueOf("efg"))
+ if i1, i2 := v1.Interface(), v2.Interface(); i1 == i2 {
+ t.Errorf("constructed arrays %v and %v should not be equal", i1, i2)
+ }
+
+ v1.Index(0).Index(0).Set(ValueOf("abc"))
+ v2.Index(0).Index(0).Set(ValueOf((v1.Index(0).Index(0).String() + " ")[:3]))
+ if i1, i2 := v1.Interface(), v2.Interface(); i1 != i2 {
+ t.Errorf("constructed arrays %v and %v should be equal", i1, i2)
+ }
+
+ // Test hash
+ m := MakeMap(MapOf(at, TypeOf(int(0))))
+ m.SetMapIndex(v1, ValueOf(1))
+ if i1, i2 := v1.Interface(), v2.Interface(); !m.MapIndex(v2).IsValid() {
+ t.Errorf("constructed arrays %v and %v have different hashes", i1, i2)
+ }
+}
+
+func TestArrayOfDirectIface(t *testing.T) {
+ t.Skip("skipping test because gccgo uses a different directiface value")
+ {
+ type T [1]*byte
+ i1 := Zero(TypeOf(T{})).Interface()
+ v1 := ValueOf(&i1).Elem()
+ p1 := v1.InterfaceData()[1]
+
+ i2 := Zero(ArrayOf(1, PtrTo(TypeOf(int8(0))))).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 [0]*byte
+ i1 := Zero(TypeOf(T{})).Interface()
+ v1 := ValueOf(&i1).Elem()
+ p1 := v1.InterfaceData()[1]
+
+ i2 := Zero(ArrayOf(0, PtrTo(TypeOf(int8(0))))).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)
+ }
+ }
+}
+
func TestSliceOf(t *testing.T) {
// check construction and use of type not in binary
type T int
@@ -3489,6 +3725,26 @@ func TestChanOf(t *testing.T) {
checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
}
+func TestChanOfDir(t *testing.T) {
+ // check construction and use of type not in binary
+ type T string
+ crt := ChanOf(RecvDir, TypeOf(T("")))
+ cst := ChanOf(SendDir, TypeOf(T("")))
+
+ // check that type already in binary is found
+ type T1 int
+ checkSameType(t, Zero(ChanOf(RecvDir, TypeOf(T1(1)))).Interface(), (<-chan T1)(nil))
+ checkSameType(t, Zero(ChanOf(SendDir, TypeOf(T1(1)))).Interface(), (chan<- T1)(nil))
+
+ // check String form of ChanDir
+ if crt.ChanDir().String() != "<-chan" {
+ t.Errorf("chan dir: have %q, want %q", crt.ChanDir().String(), "<-chan")
+ }
+ if cst.ChanDir().String() != "chan<-" {
+ t.Errorf("chan dir: have %q, want %q", cst.ChanDir().String(), "chan<-")
+ }
+}
+
func TestChanOfGC(t *testing.T) {
done := make(chan bool, 1)
go func() {
@@ -3632,6 +3888,67 @@ func TestMapOfGCValues(t *testing.T) {
}
}
+func TestTypelinksSorted(t *testing.T) {
+ var last string
+ for i, n := range TypeLinks() {
+ if n < last {
+ t.Errorf("typelinks not sorted: %q [%d] > %q [%d]", last, i-1, n, i)
+ }
+ last = n
+ }
+}
+
+func TestFuncOf(t *testing.T) {
+ // check construction and use of type not in binary
+ type K string
+ type V float64
+
+ fn := func(args []Value) []Value {
+ 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("")))
+ } else if args[0].String() != "gopher" {
+ t.Errorf("args[0] = %q, want %q", args[0].String(), "gopher")
+ }
+ return []Value{ValueOf(V(3.14))}
+ }
+ v := MakeFunc(FuncOf([]Type{TypeOf(K(""))}, []Type{TypeOf(V(0))}, false), fn)
+
+ outs := v.Call([]Value{ValueOf(K("gopher"))})
+ 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)))
+ }
+ f := outs[0].Float()
+ if f != 3.14 {
+ t.Errorf("constructed func returned %f, want %f", f, 3.14)
+ }
+
+ // check that types already in binary are found
+ type T1 int
+ testCases := []struct {
+ in, out []Type
+ variadic bool
+ want interface{}
+ }{
+ {in: []Type{TypeOf(T1(0))}, want: (func(T1))(nil)},
+ {in: []Type{TypeOf(int(0))}, want: (func(int))(nil)},
+ {in: []Type{SliceOf(TypeOf(int(0)))}, variadic: true, want: (func(...int))(nil)},
+ {in: []Type{TypeOf(int(0))}, out: []Type{TypeOf(false)}, want: (func(int) bool)(nil)},
+ {in: []Type{TypeOf(int(0))}, out: []Type{TypeOf(false), TypeOf("")}, want: (func(int) (bool, string))(nil)},
+ }
+ for _, tt := range testCases {
+ checkSameType(t, Zero(FuncOf(tt.in, tt.out, tt.variadic)).Interface(), tt.want)
+ }
+
+ // check that variadic requires last element be a slice.
+ FuncOf([]Type{TypeOf(1), TypeOf(""), SliceOf(TypeOf(false))}, nil, true)
+ shouldPanic(func() { FuncOf([]Type{TypeOf(0), TypeOf(""), TypeOf(false)}, nil, true) })
+ shouldPanic(func() { FuncOf(nil, nil, true) })
+}
+
type B1 struct {
X int
Y int
@@ -4077,15 +4394,16 @@ func TestCallGC(t *testing.T) {
}
type funcLayoutTest struct {
- rcvr, t Type
- argsize, retOffset uintptr
- stack []byte
+ rcvr, t Type
+ size, argsize, retOffset uintptr
+ stack []byte // pointer bitmap: 1 is pointer, 0 is scalar (or uninitialized)
+ gc []byte
}
var funcLayoutTests []funcLayoutTest
func init() {
- var argAlign = PtrSize
+ var argAlign uintptr = PtrSize
if runtime.GOARCH == "amd64p32" {
argAlign = 2 * PtrSize
}
@@ -4097,24 +4415,28 @@ func init() {
funcLayoutTest{
nil,
ValueOf(func(a, b string) string { return "" }).Type(),
+ 6 * PtrSize,
4 * PtrSize,
4 * PtrSize,
- []byte{BitsPointer, BitsScalar, BitsPointer},
+ []byte{1, 0, 1},
+ []byte{1, 0, 1, 0, 1},
})
var r []byte
if PtrSize == 4 {
- r = []byte{BitsScalar, BitsScalar, BitsScalar, BitsPointer}
+ r = []byte{0, 0, 0, 1}
} else {
- r = []byte{BitsScalar, BitsScalar, BitsPointer}
+ r = []byte{0, 0, 1}
}
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
nil,
ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
+ roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
roundup(3*4, PtrSize) + PtrSize + 2,
roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
r,
+ r,
})
funcLayoutTests = append(funcLayoutTests,
@@ -4123,7 +4445,9 @@ func init() {
ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
4 * PtrSize,
4 * PtrSize,
- []byte{BitsPointer, BitsScalar, BitsPointer, BitsPointer},
+ 4 * PtrSize,
+ []byte{1, 0, 1, 1},
+ []byte{1, 0, 1, 1},
})
type S struct {
@@ -4136,23 +4460,66 @@ func init() {
ValueOf(func(a S) {}).Type(),
4 * PtrSize,
4 * PtrSize,
- []byte{BitsScalar, BitsScalar, BitsPointer, BitsPointer},
+ 4 * PtrSize,
+ []byte{0, 0, 1, 1},
+ []byte{0, 0, 1, 1},
})
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
ValueOf((*byte)(nil)).Type(),
ValueOf(func(a uintptr, b *int) {}).Type(),
+ roundup(3*PtrSize, argAlign),
3 * PtrSize,
roundup(3*PtrSize, argAlign),
- []byte{BitsPointer, BitsScalar, BitsPointer},
+ []byte{1, 0, 1},
+ []byte{1, 0, 1},
+ })
+
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ nil,
+ ValueOf(func(a uintptr) {}).Type(),
+ roundup(PtrSize, argAlign),
+ PtrSize,
+ roundup(PtrSize, argAlign),
+ []byte{},
+ []byte{},
+ })
+
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ nil,
+ ValueOf(func() uintptr { return 0 }).Type(),
+ PtrSize,
+ 0,
+ 0,
+ []byte{},
+ []byte{},
+ })
+
+ funcLayoutTests = append(funcLayoutTests,
+ funcLayoutTest{
+ ValueOf(uintptr(0)).Type(),
+ ValueOf(func(a uintptr) {}).Type(),
+ 2 * PtrSize,
+ 2 * PtrSize,
+ 2 * PtrSize,
+ []byte{1},
+ []byte{1},
+ // 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.
})
}
func TestFuncLayout(t *testing.T) {
t.Skip("gccgo does not use funcLayout")
for _, lt := range funcLayoutTests {
- _, argsize, retOffset, stack := FuncLayout(lt.t, lt.rcvr)
+ typ, argsize, retOffset, stack, gc, ptrs := FuncLayout(lt.t, lt.rcvr)
+ if typ.Size() != lt.size {
+ t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.t, lt.rcvr, typ.Size(), lt.size)
+ }
if argsize != lt.argsize {
t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
}
@@ -4162,5 +4529,260 @@ func TestFuncLayout(t *testing.T) {
if !bytes.Equal(stack, lt.stack) {
t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
}
+ if !bytes.Equal(gc, lt.gc) {
+ t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.t, lt.rcvr, gc, lt.gc)
+ }
+ if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
+ t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.t, lt.rcvr, ptrs, !ptrs)
+ }
+ }
+}
+
+func verifyGCBits(t *testing.T, typ Type, bits []byte) {
+ heapBits := GCBits(New(typ).Interface())
+ if !bytes.Equal(heapBits, bits) {
+ t.Errorf("heapBits incorrect for %v\nhave %v\nwant %v", typ, heapBits, bits)
+ }
+}
+
+func verifyGCBitsSlice(t *testing.T, typ Type, cap int, bits []byte) {
+ // Creating a slice causes the runtime to repeat a bitmap,
+ // which exercises a different path from making the compiler
+ // repeat a bitmap for a small array or executing a repeat in
+ // a GC program.
+ val := MakeSlice(typ, 0, cap)
+ data := NewAt(ArrayOf(cap, typ), unsafe.Pointer(val.Pointer()))
+ heapBits := GCBits(data.Interface())
+ // Repeat the bitmap for the slice size, trimming scalars in
+ // the last element.
+ bits = rep(cap, bits)
+ for len(bits) > 2 && bits[len(bits)-1] == 0 {
+ bits = bits[:len(bits)-1]
+ }
+ if !bytes.Equal(heapBits, bits) {
+ t.Errorf("heapBits incorrect for make(%v, 0, %v)\nhave %v\nwant %v", typ, cap, heapBits, bits)
+ }
+}
+
+func TestGCBits(t *testing.T) {
+ t.Skip("gccgo does not use gcbits yet")
+
+ verifyGCBits(t, TypeOf((*byte)(nil)), []byte{1})
+
+ // Building blocks for types seen by the compiler (like [2]Xscalar).
+ // The compiler will create the type structures for the derived types,
+ // including their GC metadata.
+ type Xscalar struct{ x uintptr }
+ type Xptr struct{ x *byte }
+ type Xptrscalar struct {
+ *byte
+ uintptr
+ }
+ type Xscalarptr struct {
+ uintptr
+ *byte
+ }
+ type Xbigptrscalar struct {
+ _ [100]*byte
+ _ [100]uintptr
+ }
+
+ var Tscalar, Tint64, Tptr, Tscalarptr, Tptrscalar, Tbigptrscalar Type
+ {
+ // Building blocks for types constructed by reflect.
+ // This code is in a separate block so that code below
+ // cannot accidentally refer to these.
+ // The compiler must NOT see types derived from these
+ // (for example, [2]Scalar must NOT appear in the program),
+ // or else reflect will use it instead of having to construct one.
+ // The goal is to test the construction.
+ type Scalar struct{ x uintptr }
+ type Ptr struct{ x *byte }
+ type Ptrscalar struct {
+ *byte
+ uintptr
+ }
+ type Scalarptr struct {
+ uintptr
+ *byte
+ }
+ type Bigptrscalar struct {
+ _ [100]*byte
+ _ [100]uintptr
+ }
+ type Int64 int64
+ Tscalar = TypeOf(Scalar{})
+ Tint64 = TypeOf(Int64(0))
+ Tptr = TypeOf(Ptr{})
+ Tscalarptr = TypeOf(Scalarptr{})
+ Tptrscalar = TypeOf(Ptrscalar{})
+ Tbigptrscalar = TypeOf(Bigptrscalar{})
+ }
+
+ empty := []byte{}
+
+ verifyGCBits(t, TypeOf(Xscalar{}), empty)
+ verifyGCBits(t, Tscalar, empty)
+ verifyGCBits(t, TypeOf(Xptr{}), lit(1))
+ verifyGCBits(t, Tptr, lit(1))
+ verifyGCBits(t, TypeOf(Xscalarptr{}), lit(0, 1))
+ verifyGCBits(t, Tscalarptr, lit(0, 1))
+ verifyGCBits(t, TypeOf(Xptrscalar{}), lit(1))
+ verifyGCBits(t, Tptrscalar, lit(1))
+
+ verifyGCBits(t, TypeOf([0]Xptr{}), empty)
+ verifyGCBits(t, ArrayOf(0, Tptr), empty)
+ verifyGCBits(t, TypeOf([1]Xptrscalar{}), lit(1))
+ verifyGCBits(t, ArrayOf(1, Tptrscalar), lit(1))
+ verifyGCBits(t, TypeOf([2]Xscalar{}), empty)
+ verifyGCBits(t, ArrayOf(2, Tscalar), empty)
+ verifyGCBits(t, TypeOf([10000]Xscalar{}), empty)
+ verifyGCBits(t, ArrayOf(10000, Tscalar), empty)
+ verifyGCBits(t, TypeOf([2]Xptr{}), lit(1, 1))
+ verifyGCBits(t, ArrayOf(2, Tptr), lit(1, 1))
+ verifyGCBits(t, TypeOf([10000]Xptr{}), rep(10000, lit(1)))
+ verifyGCBits(t, ArrayOf(10000, Tptr), rep(10000, lit(1)))
+ verifyGCBits(t, TypeOf([2]Xscalarptr{}), lit(0, 1, 0, 1))
+ verifyGCBits(t, ArrayOf(2, Tscalarptr), lit(0, 1, 0, 1))
+ verifyGCBits(t, TypeOf([10000]Xscalarptr{}), rep(10000, lit(0, 1)))
+ verifyGCBits(t, ArrayOf(10000, Tscalarptr), rep(10000, lit(0, 1)))
+ verifyGCBits(t, TypeOf([2]Xptrscalar{}), lit(1, 0, 1))
+ verifyGCBits(t, ArrayOf(2, Tptrscalar), lit(1, 0, 1))
+ verifyGCBits(t, TypeOf([10000]Xptrscalar{}), rep(10000, lit(1, 0)))
+ verifyGCBits(t, ArrayOf(10000, Tptrscalar), rep(10000, lit(1, 0)))
+ verifyGCBits(t, TypeOf([1][10000]Xptrscalar{}), rep(10000, lit(1, 0)))
+ verifyGCBits(t, ArrayOf(1, ArrayOf(10000, Tptrscalar)), rep(10000, lit(1, 0)))
+ verifyGCBits(t, TypeOf([2][10000]Xptrscalar{}), rep(2*10000, lit(1, 0)))
+ verifyGCBits(t, ArrayOf(2, ArrayOf(10000, Tptrscalar)), rep(2*10000, lit(1, 0)))
+ verifyGCBits(t, TypeOf([4]Xbigptrscalar{}), join(rep(3, join(rep(100, lit(1)), rep(100, lit(0)))), rep(100, lit(1))))
+ verifyGCBits(t, ArrayOf(4, Tbigptrscalar), join(rep(3, join(rep(100, lit(1)), rep(100, lit(0)))), rep(100, lit(1))))
+
+ verifyGCBitsSlice(t, TypeOf([]Xptr{}), 0, empty)
+ verifyGCBitsSlice(t, SliceOf(Tptr), 0, empty)
+ verifyGCBitsSlice(t, TypeOf([]Xptrscalar{}), 1, lit(1))
+ verifyGCBitsSlice(t, SliceOf(Tptrscalar), 1, lit(1))
+ verifyGCBitsSlice(t, TypeOf([]Xscalar{}), 2, lit(0))
+ verifyGCBitsSlice(t, SliceOf(Tscalar), 2, lit(0))
+ verifyGCBitsSlice(t, TypeOf([]Xscalar{}), 10000, lit(0))
+ verifyGCBitsSlice(t, SliceOf(Tscalar), 10000, lit(0))
+ verifyGCBitsSlice(t, TypeOf([]Xptr{}), 2, lit(1))
+ verifyGCBitsSlice(t, SliceOf(Tptr), 2, lit(1))
+ verifyGCBitsSlice(t, TypeOf([]Xptr{}), 10000, lit(1))
+ verifyGCBitsSlice(t, SliceOf(Tptr), 10000, lit(1))
+ verifyGCBitsSlice(t, TypeOf([]Xscalarptr{}), 2, lit(0, 1))
+ verifyGCBitsSlice(t, SliceOf(Tscalarptr), 2, lit(0, 1))
+ verifyGCBitsSlice(t, TypeOf([]Xscalarptr{}), 10000, lit(0, 1))
+ verifyGCBitsSlice(t, SliceOf(Tscalarptr), 10000, lit(0, 1))
+ verifyGCBitsSlice(t, TypeOf([]Xptrscalar{}), 2, lit(1, 0))
+ verifyGCBitsSlice(t, SliceOf(Tptrscalar), 2, lit(1, 0))
+ verifyGCBitsSlice(t, TypeOf([]Xptrscalar{}), 10000, lit(1, 0))
+ verifyGCBitsSlice(t, SliceOf(Tptrscalar), 10000, lit(1, 0))
+ verifyGCBitsSlice(t, TypeOf([][10000]Xptrscalar{}), 1, rep(10000, lit(1, 0)))
+ verifyGCBitsSlice(t, SliceOf(ArrayOf(10000, Tptrscalar)), 1, rep(10000, lit(1, 0)))
+ verifyGCBitsSlice(t, TypeOf([][10000]Xptrscalar{}), 2, rep(10000, lit(1, 0)))
+ verifyGCBitsSlice(t, SliceOf(ArrayOf(10000, Tptrscalar)), 2, rep(10000, lit(1, 0)))
+ verifyGCBitsSlice(t, TypeOf([]Xbigptrscalar{}), 4, join(rep(100, lit(1)), rep(100, lit(0))))
+ verifyGCBitsSlice(t, SliceOf(Tbigptrscalar), 4, join(rep(100, lit(1)), rep(100, lit(0))))
+
+ verifyGCBits(t, TypeOf((chan [100]Xscalar)(nil)), lit(1))
+ verifyGCBits(t, ChanOf(BothDir, ArrayOf(100, Tscalar)), lit(1))
+
+ verifyGCBits(t, TypeOf((func([10000]Xscalarptr))(nil)), lit(1))
+ verifyGCBits(t, FuncOf([]Type{ArrayOf(10000, Tscalarptr)}, nil, false), lit(1))
+
+ verifyGCBits(t, TypeOf((map[[10000]Xscalarptr]Xscalar)(nil)), lit(1))
+ verifyGCBits(t, MapOf(ArrayOf(10000, Tscalarptr), Tscalar), lit(1))
+
+ verifyGCBits(t, TypeOf((*[10000]Xscalar)(nil)), lit(1))
+ verifyGCBits(t, PtrTo(ArrayOf(10000, Tscalar)), lit(1))
+
+ verifyGCBits(t, TypeOf(([][10000]Xscalar)(nil)), lit(1))
+ verifyGCBits(t, SliceOf(ArrayOf(10000, Tscalar)), lit(1))
+
+ hdr := make([]byte, 8/PtrSize)
+
+ verifyMapBucket := func(t *testing.T, k, e Type, m interface{}, want []byte) {
+ verifyGCBits(t, MapBucketOf(k, e), want)
+ verifyGCBits(t, CachedBucketOf(TypeOf(m)), want)
+ }
+ verifyMapBucket(t,
+ Tscalar, Tptr,
+ map[Xscalar]Xptr(nil),
+ join(hdr, rep(8, lit(0)), rep(8, lit(1)), lit(1)))
+ verifyMapBucket(t,
+ Tscalarptr, Tptr,
+ map[Xscalarptr]Xptr(nil),
+ join(hdr, rep(8, lit(0, 1)), rep(8, lit(1)), lit(1)))
+ verifyMapBucket(t, Tint64, Tptr,
+ map[int64]Xptr(nil),
+ join(hdr, rep(8, rep(8/PtrSize, lit(0))), rep(8, lit(1)), naclpad(), lit(1)))
+ verifyMapBucket(t,
+ Tscalar, Tscalar,
+ map[Xscalar]Xscalar(nil),
+ empty)
+ verifyMapBucket(t,
+ ArrayOf(2, Tscalarptr), ArrayOf(3, Tptrscalar),
+ map[[2]Xscalarptr][3]Xptrscalar(nil),
+ join(hdr, rep(8*2, lit(0, 1)), rep(8*3, lit(1, 0)), lit(1)))
+ verifyMapBucket(t,
+ ArrayOf(64/PtrSize, Tscalarptr), ArrayOf(64/PtrSize, Tptrscalar),
+ map[[64 / PtrSize]Xscalarptr][64 / PtrSize]Xptrscalar(nil),
+ join(hdr, rep(8*64/PtrSize, lit(0, 1)), rep(8*64/PtrSize, lit(1, 0)), lit(1)))
+ verifyMapBucket(t,
+ ArrayOf(64/PtrSize+1, Tscalarptr), ArrayOf(64/PtrSize, Tptrscalar),
+ map[[64/PtrSize + 1]Xscalarptr][64 / PtrSize]Xptrscalar(nil),
+ join(hdr, rep(8, lit(1)), rep(8*64/PtrSize, lit(1, 0)), lit(1)))
+ verifyMapBucket(t,
+ ArrayOf(64/PtrSize, Tscalarptr), ArrayOf(64/PtrSize+1, Tptrscalar),
+ map[[64 / PtrSize]Xscalarptr][64/PtrSize + 1]Xptrscalar(nil),
+ join(hdr, rep(8*64/PtrSize, lit(0, 1)), rep(8, lit(1)), lit(1)))
+ verifyMapBucket(t,
+ ArrayOf(64/PtrSize+1, Tscalarptr), ArrayOf(64/PtrSize+1, Tptrscalar),
+ map[[64/PtrSize + 1]Xscalarptr][64/PtrSize + 1]Xptrscalar(nil),
+ join(hdr, rep(8, lit(1)), rep(8, lit(1)), lit(1)))
+}
+
+func naclpad() []byte {
+ if runtime.GOARCH == "amd64p32" {
+ return lit(0)
+ }
+ return nil
+}
+
+func rep(n int, b []byte) []byte { return bytes.Repeat(b, n) }
+func join(b ...[]byte) []byte { return bytes.Join(b, nil) }
+func lit(x ...byte) []byte { return x }
+
+func TestTypeOfTypeOf(t *testing.T) {
+ // Check that all the type constructors return concrete *rtype implementations.
+ // It's difficult to test directly because the reflect package is only at arm's length.
+ // The easiest thing to do is just call a function that crashes if it doesn't get an *rtype.
+ check := func(name string, typ Type) {
+ if underlying := TypeOf(typ).String(); underlying != "*reflect.rtype" {
+ t.Errorf("%v returned %v, not *reflect.rtype", name, underlying)
+ }
+ }
+
+ type T struct{ int }
+ check("TypeOf", TypeOf(T{}))
+
+ check("ArrayOf", ArrayOf(10, TypeOf(T{})))
+ check("ChanOf", ChanOf(BothDir, TypeOf(T{})))
+ check("FuncOf", FuncOf([]Type{TypeOf(T{})}, nil, false))
+ check("MapOf", MapOf(TypeOf(T{}), TypeOf(T{})))
+ check("PtrTo", PtrTo(TypeOf(T{})))
+ check("SliceOf", SliceOf(TypeOf(T{})))
+}
+
+type XM struct{}
+
+func (*XM) String() string { return "" }
+
+func TestPtrToMethods(t *testing.T) {
+ var y struct{ XM }
+ yp := New(TypeOf(y)).Interface()
+ _, ok := yp.(fmt.Stringer)
+ if !ok {
+ t.Fatal("does not implement Stringer, but should")
}
}
OpenPOWER on IntegriCloud