diff options
Diffstat (limited to 'libgo/go/reflect/all_test.go')
-rw-r--r-- | libgo/go/reflect/all_test.go | 247 |
1 files changed, 236 insertions, 11 deletions
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index e601c2cbde2..f51e95fd734 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -648,6 +648,20 @@ var ( 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 deepEqualTests = []DeepEqualTest{ // Equalities {nil, nil, true}, @@ -706,6 +720,12 @@ var deepEqualTests = []DeepEqualTest{ {&[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 TestDeepEqual(t *testing.T) { @@ -1535,6 +1555,34 @@ func BenchmarkCall(b *testing.B) { }) } +func BenchmarkCallArgCopy(b *testing.B) { + byteArray := func(n int) Value { + return Zero(ArrayOf(n, TypeOf(byte(0)))) + } + sizes := [...]struct { + fv Value + arg Value + }{ + {ValueOf(func(a [128]byte) {}), byteArray(128)}, + {ValueOf(func(a [256]byte) {}), byteArray(256)}, + {ValueOf(func(a [1024]byte) {}), byteArray(1024)}, + {ValueOf(func(a [4096]byte) {}), byteArray(4096)}, + {ValueOf(func(a [65536]byte) {}), byteArray(65536)}, + } + for _, size := range sizes { + bench := func(b *testing.B) { + args := []Value{size.arg} + b.SetBytes(int64(size.arg.Len())) + b.ResetTimer() + for i := 0; i < b.N; i++ { + size.fv.Call(args) + } + } + name := fmt.Sprintf("size=%v", size.arg.Len()) + b.Run(name, bench) + } +} + func TestMakeFunc(t *testing.T) { f := dummy fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in }) @@ -2277,25 +2325,39 @@ func TestFieldPkgPath(t *testing.T) { unexported string OtherPkgFields }{}) - for _, test := range []struct { + + type pkgpathTest struct { index []int pkgPath string anonymous bool - }{ + } + + checkPkgPath := func(name string, s []pkgpathTest) { + for _, test := range s { + f := typ.FieldByIndex(test.index) + if got, want := f.PkgPath, test.pkgPath; got != want { + t.Errorf("%s: Field(%d).PkgPath = %q, want %q", name, test.index, got, want) + } + if got, want := f.Anonymous, test.anonymous; got != want { + t.Errorf("%s: Field(%d).Anonymous = %v, want %v", name, test.index, got, want) + } + } + } + + checkPkgPath("testStruct", []pkgpathTest{ {[]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) - } - } + }) + + type localOtherPkgFields OtherPkgFields + typ = TypeOf(localOtherPkgFields{}) + checkPkgPath("localOtherPkgFields", []pkgpathTest{ + {[]int{0}, "", false}, // OtherExported + {[]int{1}, "reflect", false}, // otherUnexported + }) } func TestVariadicType(t *testing.T) { @@ -3077,6 +3139,9 @@ func ReadWriterV(x io.ReadWriter) Value { } type Empty struct{} +type MyStruct struct { + x int `some:"tag"` +} type MyString string type MyBytes []byte type MyRunes []int32 @@ -3388,6 +3453,35 @@ var convertTests = []struct { {V((func())(nil)), V(MyFunc(nil))}, {V((MyFunc)(nil)), V((func())(nil))}, + // structs with different tags + {V(struct { + x int `some:"foo"` + }{}), V(struct { + x int `some:"bar"` + }{})}, + + {V(struct { + x int `some:"bar"` + }{}), V(struct { + x int `some:"foo"` + }{})}, + + {V(MyStruct{}), V(struct { + x int `some:"foo"` + }{})}, + + {V(struct { + x int `some:"foo"` + }{}), V(MyStruct{})}, + + {V(MyStruct{}), V(struct { + x int `some:"bar"` + }{})}, + + {V(struct { + x int `some:"bar"` + }{}), V(MyStruct{})}, + // can convert *byte and *MyByte {V((*byte)(nil)), V((*MyByte)(nil))}, {V((*MyByte)(nil)), V((*byte)(nil))}, @@ -3973,6 +4067,39 @@ func TestStructOf(t *testing.T) { } } + // Check size and alignment with a trailing zero-sized field. + st = StructOf([]StructField{ + { + Name: "F1", + Type: TypeOf(byte(0)), + }, + { + Name: "F2", + Type: TypeOf([0]*byte{}), + }, + }) + stt = TypeOf(struct { + G1 byte + G2 [0]*byte + }{}) + // Broken with gccgo for now--gccgo does not pad structs yet. + // if st.Size() != stt.Size() { + // t.Errorf("constructed zero-padded struct size = %v, want %v", st.Size(), stt.Size()) + // } + if st.Align() != stt.Align() { + t.Errorf("constructed zero-padded struct align = %v, want %v", st.Align(), stt.Align()) + } + if st.FieldAlign() != stt.FieldAlign() { + t.Errorf("constructed zero-padded 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 zero-padded struct field %v offset = %v, want %v", i, o1, o2) + } + } + // check duplicate names shouldPanic(func() { StructOf([]StructField{ @@ -5788,3 +5915,101 @@ func BenchmarkNew(b *testing.B) { New(v) } } + +func TestSwapper(t *testing.T) { + type I int + var a, b, c I + type pair struct { + x, y int + } + type pairPtr struct { + x, y int + p *I + } + type S string + + tests := []struct { + in interface{} + i, j int + want interface{} + }{ + { + in: []int{1, 20, 300}, + i: 0, + j: 2, + want: []int{300, 20, 1}, + }, + { + in: []uintptr{1, 20, 300}, + i: 0, + j: 2, + want: []uintptr{300, 20, 1}, + }, + { + in: []int16{1, 20, 300}, + i: 0, + j: 2, + want: []int16{300, 20, 1}, + }, + { + in: []int8{1, 20, 100}, + i: 0, + j: 2, + want: []int8{100, 20, 1}, + }, + { + in: []*I{&a, &b, &c}, + i: 0, + j: 2, + want: []*I{&c, &b, &a}, + }, + { + in: []string{"eric", "sergey", "larry"}, + i: 0, + j: 2, + want: []string{"larry", "sergey", "eric"}, + }, + { + in: []S{"eric", "sergey", "larry"}, + i: 0, + j: 2, + want: []S{"larry", "sergey", "eric"}, + }, + { + in: []pair{{1, 2}, {3, 4}, {5, 6}}, + i: 0, + j: 2, + want: []pair{{5, 6}, {3, 4}, {1, 2}}, + }, + { + in: []pairPtr{{1, 2, &a}, {3, 4, &b}, {5, 6, &c}}, + i: 0, + j: 2, + want: []pairPtr{{5, 6, &c}, {3, 4, &b}, {1, 2, &a}}, + }, + } + for i, tt := range tests { + inStr := fmt.Sprint(tt.in) + Swapper(tt.in)(tt.i, tt.j) + if !DeepEqual(tt.in, tt.want) { + t.Errorf("%d. swapping %v and %v of %v = %v; want %v", i, tt.i, tt.j, inStr, tt.in, tt.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) + }) +} |