cloudflared-mirror/vendor/zombiezen.com/go/capnproto2/capn_test.go

743 lines
20 KiB
Go

package capnp
import (
"bytes"
"encoding/binary"
"fmt"
"testing"
)
func TestSegmentInBounds(t *testing.T) {
tests := []struct {
n int
addr Address
ok bool
}{
{0, 0, false},
{0, 1, false},
{0, 2, false},
{1, 0, true},
{1, 1, false},
{1, 2, false},
{2, 0, true},
{2, 1, true},
{2, 2, false},
}
for _, test := range tests {
seg := &Segment{data: make([]byte, test.n)}
if ok := seg.inBounds(test.addr); ok != test.ok {
t.Errorf("&Segment{data: make([]byte, %d)}.inBounds(%#v) = %t; want %t", test.n, test.addr, ok, test.ok)
}
}
}
func TestSegmentRegionInBounds(t *testing.T) {
tests := []struct {
n int
addr Address
sz Size
ok bool
}{
{0, 0, 0, true}, // zero-sized region <= len is okay
{0, 0, 1, false},
{0, 1, 0, false},
{0, 1, 1, false},
{1, 0, 0, true},
{1, 0, 1, true},
{1, 1, 0, true},
{1, 1, 1, false},
{2, 0, 0, true},
{2, 0, 1, true},
{2, 0, 2, true},
{2, 0, 3, false},
{2, 1, 0, true},
{2, 1, 1, true},
{2, 1, 2, false},
{2, 1, 3, false},
{2, 2, 0, true},
{2, 2, 1, false},
}
for _, test := range tests {
seg := &Segment{data: make([]byte, test.n)}
if ok := seg.regionInBounds(test.addr, test.sz); ok != test.ok {
t.Errorf("&Segment{data: make([]byte, %d)}.regionInBounds(%#v, %#v) = %t; want %t", test.n, test.addr, test.sz, ok, test.ok)
}
}
}
func TestSegmentReadUint8(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint8
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{42}, addr: 0, val: 42},
{data: []byte{42}, addr: 1, panics: true},
{data: []byte{1, 42, 2}, addr: 0, val: 1},
{data: []byte{1, 42, 2}, addr: 1, val: 42},
{data: []byte{1, 42, 2}, addr: 2, val: 2},
{data: []byte{1, 42, 2}, addr: 3, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint8
err := catchPanic(func() {
val = seg.readUint8(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint8(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint8(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint8(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentReadUint16(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint16
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00}, addr: 0, val: 0},
{data: []byte{0x01, 0x00}, addr: 0, val: 1},
{data: []byte{0x34, 0x12}, addr: 0, val: 0x1234},
{data: []byte{0x34, 0x12, 0x56}, addr: 0, val: 0x1234},
{data: []byte{0x34, 0x12, 0x56}, addr: 1, val: 0x5612},
{data: []byte{0x34, 0x12, 0x56}, addr: 2, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint16
err := catchPanic(func() {
val = seg.readUint16(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint16(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint16(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint16(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentReadUint32(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint32
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00}, addr: 0, val: 0},
{data: []byte{0x78, 0x56, 0x34, 0x12}, addr: 0, val: 0x12345678},
{data: []byte{0xff, 0x78, 0x56, 0x34, 0x12, 0xff}, addr: 1, val: 0x12345678},
{data: []byte{0xff, 0x78, 0x56, 0x34, 0x12, 0xff}, addr: 2, val: 0xff123456},
{data: []byte{0xff, 0x78, 0x56, 0x34, 0x12, 0xff}, addr: 3, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint32
err := catchPanic(func() {
val = seg.readUint32(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint32(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint32(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint32(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentReadUint64(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint64
panics bool
}{
{data: []byte{}, addr: 0, panics: true},
{data: []byte{0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, panics: true},
{data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, addr: 0, val: 0},
{data: []byte{0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01}, addr: 0, val: 0x0123456789abcdef},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 0, val: 0x23456789abcdefff},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 1, val: 0x0123456789abcdef},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 2, val: 0xff0123456789abcd},
{data: []byte{0xff, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff}, addr: 3, panics: true},
}
for _, test := range tests {
seg := &Segment{data: test.data}
var val uint64
err := catchPanic(func() {
val = seg.readUint64(test.addr)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.readUint64(%v) unexpected panic: %v", test.data, test.addr, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.readUint64(%v) did not panic as expected", test.data, test.addr)
continue
}
if val != test.val {
t.Errorf("&Segment{data: % x}.readUint64(%v) = %#x; want %#x", test.data, test.addr, val, test.val)
}
}
}
func TestSegmentWriteUint8(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint8
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1},
addr: 0,
val: 42,
out: []byte{42},
},
{
data: []byte{42},
addr: 1,
val: 1,
panics: true,
},
{
data: []byte{1, 2, 3},
addr: 0,
val: 0xff,
out: []byte{0xff, 2, 3},
},
{
data: []byte{1, 2, 3},
addr: 1,
val: 0xff,
out: []byte{1, 0xff, 3},
},
{
data: []byte{1, 2, 3},
addr: 2,
val: 0xff,
out: []byte{1, 2, 0xff},
},
{
data: []byte{1, 2, 3},
addr: 3,
val: 0xff,
panics: true,
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint8(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint8(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint8(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint8(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSegmentWriteUint16(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint16
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1, 2, 3, 4},
addr: 1,
val: 0x1234,
out: []byte{1, 0x34, 0x12, 4},
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint16(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint16(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint16(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint16(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSegmentWriteUint32(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint32
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1, 2, 3, 4, 5, 6},
addr: 1,
val: 0x01234567,
out: []byte{1, 0x67, 0x45, 0x23, 0x01, 6},
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint32(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint32(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint32(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint32(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSegmentWriteUint64(t *testing.T) {
tests := []struct {
data []byte
addr Address
val uint64
out []byte
panics bool
}{
{
data: []byte{},
addr: 0,
val: 0,
panics: true,
},
{
data: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
addr: 1,
val: 0x0123456789abcdef,
out: []byte{1, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 10},
},
}
for _, test := range tests {
out := make([]byte, len(test.data))
copy(out, test.data)
seg := &Segment{data: out}
err := catchPanic(func() {
seg.writeUint64(test.addr, test.val)
})
if err != nil {
if !test.panics {
t.Errorf("&Segment{data: % x}.writeUint64(%v, %#x) unexpected panic: %v", test.data, test.addr, test.val, err)
}
continue
}
if test.panics {
t.Errorf("&Segment{data: % x}.writeUint64(%v, %#x) did not panic as expected", test.data, test.addr, test.val)
continue
}
if !bytes.Equal(out, test.out) {
t.Errorf("data after &Segment{data: % x}.writeUint64(%v, %#x) = % x; want % x", test.data, test.addr, test.val, out, test.out)
}
}
}
func TestSetPtrCopyListMember(t *testing.T) {
_, seg, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal("NewMessage:", err)
}
root, err := NewRootStruct(seg, ObjectSize{PointerCount: 2})
if err != nil {
t.Fatal("NewRootStruct:", err)
}
plist, err := NewCompositeList(seg, ObjectSize{PointerCount: 1}, 1)
if err != nil {
t.Fatal("NewCompositeList:", err)
}
if err := root.SetPtr(0, plist.ToPtr()); err != nil {
t.Fatal("root.SetPtr(0, plist):", err)
}
sub, err := NewStruct(seg, ObjectSize{DataSize: 8})
if err != nil {
t.Fatal("NewStruct:", err)
}
sub.SetUint64(0, 42)
pl0 := plist.Struct(0)
if err := pl0.SetPtr(0, sub.ToPtr()); err != nil {
t.Fatal("pl0.SetPtr(0, sub.ToPtr()):", err)
}
if err := root.SetPtr(1, pl0.ToPtr()); err != nil {
t.Error("root.SetPtr(1, pl0):", err)
}
p1, err := root.Ptr(1)
if err != nil {
t.Error("root.Ptr(1):", err)
}
s1 := p1.Struct()
if !s1.IsValid() {
t.Error("root.Ptr(1) is not a valid struct")
}
if SamePtr(s1.ToPtr(), pl0.ToPtr()) {
t.Error("list member not copied; points to same object")
}
s1p0, err := s1.Ptr(0)
if err != nil {
t.Error("root.Ptr(1).Struct().Ptr(0):", err)
}
s1s0 := s1p0.Struct()
if !s1s0.IsValid() {
t.Error("root.Ptr(1).Struct().Ptr(0) is not a valid struct")
}
if SamePtr(s1s0.ToPtr(), sub.ToPtr()) {
t.Error("sub-object not copied; points to same object")
}
if got := s1s0.Uint64(0); got != 42 {
t.Errorf("sub-object data = %d; want 42", got)
}
}
func TestSetPtrToZeroSizeStruct(t *testing.T) {
_, seg, err := NewMessage(SingleSegment(nil))
if err != nil {
t.Fatal("NewMessage:", err)
}
root, err := NewRootStruct(seg, ObjectSize{PointerCount: 1})
if err != nil {
t.Fatal("NewRootStruct:", err)
}
sub, err := NewStruct(seg, ObjectSize{})
if err != nil {
t.Fatal("NewStruct:", err)
}
if err := root.SetPtr(0, sub.ToPtr()); err != nil {
t.Fatal("root.SetPtr(0, sub.ToPtr()):", err)
}
ptrSlice := seg.Data()[root.off : root.off+8]
want := []byte{0xfc, 0xff, 0xff, 0xff, 0, 0, 0, 0}
if !bytes.Equal(ptrSlice, want) {
t.Errorf("SetPtr wrote % 02x; want % 02x", ptrSlice, want)
}
}
func TestReadFarPointers(t *testing.T) {
msg := &Message{
// an rpc.capnp Message
Arena: MultiSegment([][]byte{
// Segment 0
{
// Double-far pointer: segment 2, offset 0
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
},
// Segment 1
{
// (Root) Struct data section
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Struct pointer section
// Double-far pointer: segment 4, offset 0
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
},
// Segment 2
{
// Far pointer landing pad: segment 1, offset 0
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
// Far pointer landing pad tag word: struct with 1 word data and 1 pointer
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
},
// Segment 3
{
// (Root>0) Struct data section
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0xaa, 0x70, 0x65, 0x21, 0xd7, 0x7b, 0x31, 0xa7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Struct pointer section
// Far pointer: segment 4, offset 4
0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
// Far pointer: segment 4, offset 7
0x3a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
// Null
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
// Segment 4
{
// Far pointer landing pad: segment 3, offset 0
0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
// Far pointer landing pad tag word: struct with 3 word data and 3 pointer
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
// (Root>0>0) Struct data section
0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Struct pointer section
// Null
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Far pointer landing pad: struct pointer: offset -3, 1 word data, 1 pointer
0xf4, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00,
// (Root>0>1) Struct pointer section
// Struct pointer: offset 2, 1 word data
0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
// Null
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Far pointer landing pad: struct pointer: offset -3, 2 pointers
0xf4, 0xff, 0xff, 0xff, 0x00, 0x00, 0x02, 0x00,
// (Root>0>1>0) Struct data section
0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
}),
}
rootp, err := msg.RootPtr()
if err != nil {
t.Error("RootPtr:", err)
}
root := rootp.Struct()
if root.Uint16(0) != 2 {
t.Errorf("root.Uint16(0) = %d; want 2", root.Uint16(0))
}
callp, err := root.Ptr(0)
if err != nil {
t.Error("root.Ptr(0):", err)
}
call := callp.Struct()
targetp, err := call.Ptr(0)
if err != nil {
t.Error("root.Ptr(0).Ptr(0):", err)
}
if got := targetp.Struct().Uint32(0); got != 84 {
t.Errorf("root.Ptr(0).Ptr(0).Uint32(0) = %d; want 84", got)
}
paramsp, err := call.Ptr(1)
if err != nil {
t.Error("root.Ptr(0).Ptr(1):", err)
}
contentp, err := paramsp.Struct().Ptr(0)
if err != nil {
t.Error("root.Ptr(0).Ptr(1).Ptr(0):", err)
}
if got := contentp.Struct().Uint64(0); got != 42 {
t.Errorf("root.Ptr(0).Ptr(1).Ptr(0).Uint64(0) = %d; want 42", got)
}
}
func TestWriteFarPointer(t *testing.T) {
// TODO(someday): run same test with a two-word list
msg := &Message{
Arena: MultiSegment([][]byte{
make([]byte, 8),
make([]byte, 0, 24),
}),
}
seg1, err := msg.Segment(1)
if err != nil {
t.Fatal("msg.Segment(1):", err)
}
s, err := NewStruct(seg1, ObjectSize{DataSize: 8, PointerCount: 1})
if err != nil {
t.Fatal("NewStruct(msg.Segment(1), ObjectSize{8, 1}):", err)
}
if s.Segment() != seg1 {
t.Fatalf("struct allocated in segment %d", s.Segment().ID())
}
if err := msg.SetRootPtr(s.ToPtr()); err != nil {
t.Error("msg.SetRootPtr(...):", err)
}
seg0, err := msg.Segment(0)
if err != nil {
t.Fatal("msg.Segment(0):", err)
}
root := rawPointer(binary.LittleEndian.Uint64(seg0.Data()))
if root.pointerType() != farPointer {
t.Fatalf("root (%#016x) type = %v; want %v (farPointer)", root, root.pointerType(), farPointer)
}
if root.farSegment() != 1 {
t.Fatalf("root points to segment %d; want 1", root.farSegment())
}
padAddr := root.farAddress()
if padAddr > Address(len(seg1.Data())-8) {
t.Fatalf("root points to out of bounds address %v; size of segment is %d", padAddr, len(seg1.Data()))
}
pad := rawPointer(binary.LittleEndian.Uint64(seg1.Data()[padAddr:]))
if pad.pointerType() != structPointer {
t.Errorf("landing pad (%#016x) type = %v; want %v (structPointer)", pad, pad.pointerType(), structPointer)
}
if got, ok := pad.offset().resolve(padAddr + 8); !ok || got != s.off {
t.Errorf("landing pad (%#016x @ %v) resolved address = %v, %t; want %v, true", pad, padAddr, got, ok, s.off)
}
if got, want := pad.structSize(), (ObjectSize{DataSize: 8, PointerCount: 1}); got != want {
t.Errorf("landing pad (%#016x) struct size = %v; want %v", pad, got, want)
}
}
func TestWriteDoubleFarPointer(t *testing.T) {
// TODO(someday): run same test with a two-word list
msg := &Message{
Arena: MultiSegment([][]byte{
make([]byte, 8),
make([]byte, 0, 16),
}),
}
seg1, err := msg.Segment(1)
if err != nil {
t.Fatal("msg.Segment(1):", err)
}
s, err := NewStruct(seg1, ObjectSize{DataSize: 8, PointerCount: 1})
if err != nil {
t.Fatal("NewStruct(msg.Segment(1), ObjectSize{8, 1}):", err)
}
if s.Segment() != seg1 {
t.Fatalf("struct allocated in segment %d", s.Segment().ID())
}
if err := msg.SetRootPtr(s.ToPtr()); err != nil {
t.Error("msg.SetRootPtr(...):", err)
}
seg0, err := msg.Segment(0)
if err != nil {
t.Fatal("msg.Segment(0):", err)
}
root := rawPointer(binary.LittleEndian.Uint64(seg0.Data()))
if root.pointerType() != doubleFarPointer {
t.Fatalf("root (%#016x) type = %v; want %v (doubleFarPointer)", root, root.pointerType(), doubleFarPointer)
}
if root.farSegment() == 0 || root.farSegment() == 1 {
t.Fatalf("root points to segment %d; want !=0,1", root.farSegment())
}
padSeg, err := msg.Segment(root.farSegment())
if err != nil {
t.Fatalf("msg.Segment(%d): %v", root.farSegment(), err)
}
padAddr := root.farAddress()
if padAddr > Address(len(padSeg.Data())-16) {
t.Fatalf("root points to out of bounds address %v; size of segment is %d", padAddr, len(padSeg.Data()))
}
pad1 := rawPointer(binary.LittleEndian.Uint64(padSeg.Data()[padAddr:]))
if pad1.pointerType() != farPointer {
t.Errorf("landing pad pointer 1 (%#016x) type = %v; want %v (farPointer)", pad1, pad1.pointerType(), farPointer)
}
if pad1.farSegment() != 1 {
t.Fatalf("landing pad pointer 1 (%#016x) points to segment %d; want 1", pad1, pad1.farSegment())
}
if pad1.farAddress() != s.off {
t.Fatalf("landing pad pointer 1 (%#016x) points to address %v; want %v", pad1, pad1.farAddress(), s.off)
}
pad2 := rawPointer(binary.LittleEndian.Uint64(padSeg.Data()[padAddr+8:]))
if pad2.pointerType() != structPointer {
t.Errorf("landing pad pointer 2 (%#016x) type = %v; want %v (structPointer)", pad2, pad2.pointerType(), structPointer)
}
if pad2.offset() != 0 {
t.Errorf("landing pad pointer 2 (%#016x) offset = %d; want 0", pad2, pad2.offset())
}
if got, want := pad2.structSize(), (ObjectSize{DataSize: 8, PointerCount: 1}); got != want {
t.Errorf("landing pad pointer 2 (%#016x) struct size = %v; want %v", pad2, got, want)
}
}
func catchPanic(f func()) (err error) {
defer func() {
pval := recover()
if pval == nil {
return
}
e, ok := pval.(error)
if !ok {
err = fmt.Errorf("non-error panic: %#v", pval)
return
}
err = e
}()
f()
return nil
}