1473 lines
38 KiB
Go
1473 lines
38 KiB
Go
|
package pogs
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/kylelemons/godebug/pretty"
|
||
|
"zombiezen.com/go/capnproto2"
|
||
|
air "zombiezen.com/go/capnproto2/internal/aircraftlib"
|
||
|
)
|
||
|
|
||
|
type Z struct {
|
||
|
Which air.Z_Which
|
||
|
|
||
|
F64 float64
|
||
|
F32 float32
|
||
|
|
||
|
I64 int64
|
||
|
I32 int32
|
||
|
I16 int16
|
||
|
I8 int8
|
||
|
|
||
|
U64 uint64
|
||
|
U32 uint32
|
||
|
U16 uint16
|
||
|
U8 uint8
|
||
|
|
||
|
Bool bool
|
||
|
Text string
|
||
|
Blob []byte
|
||
|
|
||
|
F64vec []float64
|
||
|
F32vec []float32
|
||
|
|
||
|
I64vec []int64
|
||
|
I8vec []int8
|
||
|
|
||
|
U64vec []uint64
|
||
|
U8vec []uint8
|
||
|
|
||
|
Boolvec []bool
|
||
|
Datavec [][]byte
|
||
|
Textvec []string
|
||
|
|
||
|
Zvec []*Z
|
||
|
Zvecvec [][]*Z
|
||
|
|
||
|
Planebase *PlaneBase
|
||
|
Airport air.Airport
|
||
|
|
||
|
Grp *ZGroup
|
||
|
|
||
|
Echo air.Echo
|
||
|
|
||
|
EchoBases EchoBases
|
||
|
}
|
||
|
|
||
|
type PlaneBase struct {
|
||
|
Name string
|
||
|
Homes []air.Airport
|
||
|
Rating int64
|
||
|
CanFly bool
|
||
|
Capacity int64
|
||
|
MaxSpeed float64
|
||
|
}
|
||
|
|
||
|
func (p *PlaneBase) equal(q *PlaneBase) bool {
|
||
|
if p == nil && q == nil {
|
||
|
return true
|
||
|
}
|
||
|
if (p == nil) != (q == nil) {
|
||
|
return false
|
||
|
}
|
||
|
if len(p.Homes) != len(q.Homes) {
|
||
|
return false
|
||
|
}
|
||
|
for i := range p.Homes {
|
||
|
if p.Homes[i] != q.Homes[i] {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return p.Name == q.Name &&
|
||
|
p.Rating == q.Rating &&
|
||
|
p.CanFly == q.CanFly &&
|
||
|
p.Capacity == q.Capacity &&
|
||
|
p.MaxSpeed == q.MaxSpeed
|
||
|
}
|
||
|
|
||
|
type ZGroup struct {
|
||
|
First uint64
|
||
|
Second uint64
|
||
|
}
|
||
|
|
||
|
var goodTests = []Z{
|
||
|
{Which: air.Z_Which_f64, F64: 3.5},
|
||
|
{Which: air.Z_Which_f32, F32: 3.5},
|
||
|
{Which: air.Z_Which_i64, I64: -123},
|
||
|
{Which: air.Z_Which_i32, I32: -123},
|
||
|
{Which: air.Z_Which_i16, I16: -123},
|
||
|
{Which: air.Z_Which_i8, I8: -123},
|
||
|
{Which: air.Z_Which_u64, U64: 123},
|
||
|
{Which: air.Z_Which_u32, U32: 123},
|
||
|
{Which: air.Z_Which_u16, U16: 123},
|
||
|
{Which: air.Z_Which_u8, U8: 123},
|
||
|
{Which: air.Z_Which_bool, Bool: true},
|
||
|
{Which: air.Z_Which_bool, Bool: false},
|
||
|
{Which: air.Z_Which_text, Text: "Hello, World!"},
|
||
|
{Which: air.Z_Which_blob, Blob: nil},
|
||
|
{Which: air.Z_Which_blob, Blob: []byte{}},
|
||
|
{Which: air.Z_Which_blob, Blob: []byte("Hello, World!")},
|
||
|
{Which: air.Z_Which_f64vec, F64vec: nil},
|
||
|
{Which: air.Z_Which_f64vec, F64vec: []float64{-2.0, 4.5}},
|
||
|
{Which: air.Z_Which_f32vec, F32vec: nil},
|
||
|
{Which: air.Z_Which_f32vec, F32vec: []float32{-2.0, 4.5}},
|
||
|
{Which: air.Z_Which_i64vec, I64vec: nil},
|
||
|
{Which: air.Z_Which_i64vec, I64vec: []int64{-123, 0, 123}},
|
||
|
{Which: air.Z_Which_i8vec, I8vec: nil},
|
||
|
{Which: air.Z_Which_i8vec, I8vec: []int8{-123, 0, 123}},
|
||
|
{Which: air.Z_Which_u64vec, U64vec: nil},
|
||
|
{Which: air.Z_Which_u64vec, U64vec: []uint64{0, 123}},
|
||
|
{Which: air.Z_Which_u8vec, U8vec: nil},
|
||
|
{Which: air.Z_Which_u8vec, U8vec: []uint8{0, 123}},
|
||
|
{Which: air.Z_Which_boolvec, Boolvec: nil},
|
||
|
{Which: air.Z_Which_boolvec, Boolvec: []bool{false, true, false}},
|
||
|
{Which: air.Z_Which_datavec, Datavec: nil},
|
||
|
{Which: air.Z_Which_datavec, Datavec: [][]byte{[]byte("hi"), []byte("bye")}},
|
||
|
{Which: air.Z_Which_datavec, Datavec: [][]byte{nil, nil, nil}},
|
||
|
{Which: air.Z_Which_textvec, Textvec: nil},
|
||
|
{Which: air.Z_Which_textvec, Textvec: []string{"John", "Paul", "George", "Ringo"}},
|
||
|
{Which: air.Z_Which_textvec, Textvec: []string{"", "", ""}},
|
||
|
{Which: air.Z_Which_zvec, Zvec: []*Z{
|
||
|
{Which: air.Z_Which_i64, I64: -123},
|
||
|
{Which: air.Z_Which_text, Text: "Hi"},
|
||
|
}},
|
||
|
{Which: air.Z_Which_zvecvec, Zvecvec: [][]*Z{
|
||
|
{
|
||
|
{Which: air.Z_Which_i64, I64: 1},
|
||
|
{Which: air.Z_Which_i64, I64: 2},
|
||
|
},
|
||
|
{
|
||
|
{Which: air.Z_Which_i64, I64: 3},
|
||
|
{Which: air.Z_Which_i64, I64: 4},
|
||
|
},
|
||
|
}},
|
||
|
{Which: air.Z_Which_planebase, Planebase: nil},
|
||
|
{Which: air.Z_Which_planebase, Planebase: &PlaneBase{
|
||
|
Name: "Boeing",
|
||
|
Homes: []air.Airport{air.Airport_lax, air.Airport_dfw},
|
||
|
Rating: 123,
|
||
|
CanFly: true,
|
||
|
Capacity: 100,
|
||
|
MaxSpeed: 9001.0,
|
||
|
}},
|
||
|
{Which: air.Z_Which_airport, Airport: air.Airport_lax},
|
||
|
{Which: air.Z_Which_grp, Grp: &ZGroup{First: 123, Second: 456}},
|
||
|
{Which: air.Z_Which_echo, Echo: air.Echo_ServerToClient(simpleEcho{})},
|
||
|
{Which: air.Z_Which_echo, Echo: air.Echo{Client: nil}},
|
||
|
{Which: air.Z_Which_echoBases, EchoBases: EchoBases{
|
||
|
Bases: []EchoBase{
|
||
|
{Echo: air.Echo{Client: nil}},
|
||
|
{Echo: air.Echo_ServerToClient(simpleEcho{})},
|
||
|
{Echo: air.Echo{Client: nil}},
|
||
|
{Echo: air.Echo_ServerToClient(simpleEcho{})},
|
||
|
{Echo: air.Echo{Client: nil}},
|
||
|
},
|
||
|
}},
|
||
|
}
|
||
|
|
||
|
func TestExtract(t *testing.T) {
|
||
|
for _, test := range goodTests {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Errorf("NewMessage for %s: %v", zpretty.Sprint(test), err)
|
||
|
continue
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Errorf("NewRootZ for %s: %v", zpretty.Sprint(test), err)
|
||
|
continue
|
||
|
}
|
||
|
if err := zfill(z, &test); err != nil {
|
||
|
t.Errorf("zfill for %s: %v", zpretty.Sprint(test), err)
|
||
|
continue
|
||
|
}
|
||
|
out := new(Z)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract(%v) error: %v", z, err)
|
||
|
}
|
||
|
if !test.equal(out) {
|
||
|
t.Errorf("Extract(%v) produced %s; want %s", z, zpretty.Sprint(out), zpretty.Sprint(test))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert(t *testing.T) {
|
||
|
for _, test := range goodTests {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Errorf("NewMessage for %s: %v", zpretty.Sprint(test), err)
|
||
|
continue
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Errorf("NewRootZ for %s: %v", zpretty.Sprint(test), err)
|
||
|
continue
|
||
|
}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, &test)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(test), err)
|
||
|
}
|
||
|
if equal, err := zequal(&test, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(test), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(test), z)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_Size(t *testing.T) {
|
||
|
const baseSize = 8
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
sz capnp.ObjectSize
|
||
|
z Z
|
||
|
ok bool
|
||
|
}{
|
||
|
{
|
||
|
name: "void into empty",
|
||
|
z: Z{Which: air.Z_Which_void},
|
||
|
},
|
||
|
{
|
||
|
name: "void into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_void},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "void into 1-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 1},
|
||
|
z: Z{Which: air.Z_Which_void},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "bool into empty",
|
||
|
z: Z{Which: air.Z_Which_bool, Bool: true},
|
||
|
},
|
||
|
{
|
||
|
name: "bool into 0 byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_bool, Bool: true},
|
||
|
},
|
||
|
{
|
||
|
name: "bool into 1 byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 1},
|
||
|
z: Z{Which: air.Z_Which_bool, Bool: true},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "bool into 0 byte, 1-pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 1},
|
||
|
z: Z{Which: air.Z_Which_bool, Bool: true},
|
||
|
},
|
||
|
{
|
||
|
name: "int8 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_i8, I8: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "int8 into 1-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 1},
|
||
|
z: Z{Which: air.Z_Which_i8, I8: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "uint8 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_u8, U8: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "uint8 into 1-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 1},
|
||
|
z: Z{Which: air.Z_Which_u8, U8: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "int16 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_i16, I16: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "int16 into 2-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 2},
|
||
|
z: Z{Which: air.Z_Which_i16, I16: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "uint16 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_u16, U16: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "uint16 into 2-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 2},
|
||
|
z: Z{Which: air.Z_Which_u16, U16: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "enum into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_airport, Airport: air.Airport_jfk},
|
||
|
},
|
||
|
{
|
||
|
name: "enum into 2-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 2},
|
||
|
z: Z{Which: air.Z_Which_airport, Airport: air.Airport_jfk},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "int32 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_i32, I32: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "int32 into 4-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 4},
|
||
|
z: Z{Which: air.Z_Which_i32, I32: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "uint32 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_u32, U32: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "uint32 into 4-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 4},
|
||
|
z: Z{Which: air.Z_Which_u32, U32: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "float32 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_f32, F32: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "float32 into 4-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 4},
|
||
|
z: Z{Which: air.Z_Which_f32, F32: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "int64 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_i64, I64: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "int64 into 8-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 8},
|
||
|
z: Z{Which: air.Z_Which_i64, I64: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "uint64 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_u64, U64: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "uint64 into 8-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 8},
|
||
|
z: Z{Which: air.Z_Which_u64, U64: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "float64 into 0-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize},
|
||
|
z: Z{Which: air.Z_Which_f64, F64: 123},
|
||
|
},
|
||
|
{
|
||
|
name: "float64 into 8-byte",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize + 8},
|
||
|
z: Z{Which: air.Z_Which_f64, F64: 123},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "text into 0 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 0},
|
||
|
z: Z{Which: air.Z_Which_text, Text: "hi"},
|
||
|
},
|
||
|
{
|
||
|
name: "text into 1 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 1},
|
||
|
z: Z{Which: air.Z_Which_text, Text: "hi"},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "data into 0 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 0},
|
||
|
z: Z{Which: air.Z_Which_blob, Blob: []byte("hi")},
|
||
|
},
|
||
|
{
|
||
|
name: "data into 1 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 1},
|
||
|
z: Z{Which: air.Z_Which_blob, Blob: []byte("hi")},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "list into 0 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 0},
|
||
|
z: Z{Which: air.Z_Which_f64vec, F64vec: []float64{123}},
|
||
|
},
|
||
|
{
|
||
|
name: "list into 1 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 1},
|
||
|
z: Z{Which: air.Z_Which_f64vec, F64vec: []float64{123}},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "struct into 0 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 0},
|
||
|
z: Z{Which: air.Z_Which_planebase, Planebase: new(PlaneBase)},
|
||
|
},
|
||
|
{
|
||
|
name: "struct into 1 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 1},
|
||
|
z: Z{Which: air.Z_Which_planebase, Planebase: new(PlaneBase)},
|
||
|
ok: true,
|
||
|
},
|
||
|
{
|
||
|
name: "interface into 0 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 0},
|
||
|
z: Z{
|
||
|
Which: air.Z_Which_echo,
|
||
|
Echo: air.Echo_ServerToClient(simpleEcho{}),
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "interface into 1 pointer",
|
||
|
sz: capnp.ObjectSize{DataSize: baseSize, PointerCount: 1},
|
||
|
z: Z{
|
||
|
Which: air.Z_Which_echo,
|
||
|
Echo: air.Echo_ServerToClient(simpleEcho{}),
|
||
|
},
|
||
|
ok: true,
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: NewMessage: %v", test.name, err)
|
||
|
continue
|
||
|
}
|
||
|
st, err := capnp.NewRootStruct(seg, test.sz)
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: NewRootStruct(seg, %v): %v", test.name, test.sz, err)
|
||
|
continue
|
||
|
}
|
||
|
err = Insert(air.Z_TypeID, st, &test.z)
|
||
|
if test.ok && err != nil {
|
||
|
t.Errorf("%s: Insert(%#x, capnp.NewStruct(seg, %v), %s) = %v; want nil", test.name, uint64(air.Z_TypeID), test.sz, zpretty.Sprint(test.z), err)
|
||
|
}
|
||
|
if !test.ok && err == nil {
|
||
|
t.Errorf("%s: Insert(%#x, capnp.NewStruct(seg, %v), %s) = nil; want error about not fitting", test.name, uint64(air.Z_TypeID), test.sz, zpretty.Sprint(test.z))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type BytesZ struct {
|
||
|
Which air.Z_Which
|
||
|
Text []byte
|
||
|
Textvec [][]byte
|
||
|
}
|
||
|
|
||
|
func TestExtract_StringBytes(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
err = zfill(z, &Z{Which: air.Z_Which_text, Text: "Hello, World!"})
|
||
|
if err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(BytesZ)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract(%v) error: %v", z, err)
|
||
|
}
|
||
|
want := &BytesZ{Which: air.Z_Which_text, Text: []byte("Hello, World!")}
|
||
|
if out.Which != want.Which || !bytes.Equal(out.Text, want.Text) {
|
||
|
t.Errorf("Extract(%v) produced %s; want %s", z, zpretty.Sprint(out), zpretty.Sprint(want))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestExtract_StringListBytes(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
err = zfill(z, &Z{Which: air.Z_Which_textvec, Textvec: []string{"Holmes", "Watson"}})
|
||
|
if err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(BytesZ)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract(%v) error: %v", z, err)
|
||
|
}
|
||
|
want := &BytesZ{Which: air.Z_Which_textvec, Textvec: [][]byte{[]byte("Holmes"), []byte("Watson")}}
|
||
|
eq := sliceeq(len(out.Textvec), len(want.Textvec), func(i int) bool {
|
||
|
return bytes.Equal(out.Textvec[i], want.Textvec[i])
|
||
|
})
|
||
|
if out.Which != want.Which || !eq {
|
||
|
t.Errorf("Extract(%v) produced %s; want %s", z, zpretty.Sprint(out), zpretty.Sprint(want))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_StringBytes(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
bz := &BytesZ{Which: air.Z_Which_text, Text: []byte("Hello, World!")}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, bz)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(bz), err)
|
||
|
}
|
||
|
want := &Z{Which: air.Z_Which_text, Text: "Hello, World!"}
|
||
|
if equal, err := zequal(want, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(bz), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(bz), z)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_StringListBytes(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
bz := &BytesZ{Which: air.Z_Which_textvec, Textvec: [][]byte{[]byte("Holmes"), []byte("Watson")}}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, bz)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(bz), err)
|
||
|
}
|
||
|
want := &Z{Which: air.Z_Which_textvec, Textvec: []string{"Holmes", "Watson"}}
|
||
|
if equal, err := zequal(want, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(bz), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(bz), z)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// StructZ is a variant of Z that has direct structs instead of pointers.
|
||
|
type StructZ struct {
|
||
|
Which air.Z_Which
|
||
|
Zvec []Z
|
||
|
Planebase PlaneBase
|
||
|
Grp ZGroup
|
||
|
}
|
||
|
|
||
|
func (z *StructZ) equal(y *StructZ) bool {
|
||
|
if z.Which != y.Which {
|
||
|
return false
|
||
|
}
|
||
|
switch z.Which {
|
||
|
case air.Z_Which_zvec:
|
||
|
return sliceeq(len(z.Zvec), len(y.Zvec), func(i int) bool {
|
||
|
return z.Zvec[i].equal(&y.Zvec[i])
|
||
|
})
|
||
|
case air.Z_Which_planebase:
|
||
|
return z.Planebase.equal(&y.Planebase)
|
||
|
case air.Z_Which_grp:
|
||
|
return z.Grp.First == y.Grp.First && z.Grp.Second == y.Grp.Second
|
||
|
default:
|
||
|
panic("unknown Z which")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestExtract_StructNoPtr(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
err = zfill(z, &Z{Which: air.Z_Which_planebase, Planebase: &PlaneBase{Name: "foo"}})
|
||
|
if err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(StructZ)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract(%v) error: %v", z, err)
|
||
|
}
|
||
|
want := &StructZ{Which: air.Z_Which_planebase, Planebase: PlaneBase{Name: "foo"}}
|
||
|
if !out.equal(want) {
|
||
|
t.Errorf("Extract(%v) produced %s; want %s", z, zpretty.Sprint(out), zpretty.Sprint(want))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestExtract_StructListNoPtr(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
err = zfill(z, &Z{Which: air.Z_Which_zvec, Zvec: []*Z{
|
||
|
{Which: air.Z_Which_i64, I64: 123},
|
||
|
}})
|
||
|
if err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(StructZ)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract(%v) error: %v", z, err)
|
||
|
}
|
||
|
want := &StructZ{Which: air.Z_Which_zvec, Zvec: []Z{
|
||
|
{Which: air.Z_Which_i64, I64: 123},
|
||
|
}}
|
||
|
if !out.equal(want) {
|
||
|
t.Errorf("Extract(%v) produced %s; want %s", z, zpretty.Sprint(out), zpretty.Sprint(want))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestExtract_GroupNoPtr(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
err = zfill(z, &Z{Which: air.Z_Which_grp, Grp: &ZGroup{First: 123, Second: 456}})
|
||
|
if err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(StructZ)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract(%v) error: %v", z, err)
|
||
|
}
|
||
|
want := &StructZ{Which: air.Z_Which_grp, Grp: ZGroup{First: 123, Second: 456}}
|
||
|
if !out.equal(want) {
|
||
|
t.Errorf("Extract(%v) produced %s; want %s", z, zpretty.Sprint(out), zpretty.Sprint(want))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_StructNoPtr(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
bz := &StructZ{Which: air.Z_Which_planebase, Planebase: PlaneBase{Name: "foo"}}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, bz)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(bz), err)
|
||
|
}
|
||
|
want := &Z{Which: air.Z_Which_planebase, Planebase: &PlaneBase{Name: "foo"}}
|
||
|
if equal, err := zequal(want, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(bz), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(bz), z)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_StructListNoPtr(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
bz := &StructZ{Which: air.Z_Which_zvec, Zvec: []Z{
|
||
|
{Which: air.Z_Which_i64, I64: 123},
|
||
|
}}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, bz)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(bz), err)
|
||
|
}
|
||
|
want := &Z{Which: air.Z_Which_zvec, Zvec: []*Z{
|
||
|
{Which: air.Z_Which_i64, I64: 123},
|
||
|
}}
|
||
|
if equal, err := zequal(want, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(bz), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(bz), z)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_GroupNoPtr(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
bz := &StructZ{Which: air.Z_Which_grp, Grp: ZGroup{First: 123, Second: 456}}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, bz)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(bz), err)
|
||
|
}
|
||
|
want := &Z{Which: air.Z_Which_grp, Grp: &ZGroup{First: 123, Second: 456}}
|
||
|
if equal, err := zequal(want, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(bz), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(bz), z)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TagZ is a variant of Z that has tags.
|
||
|
type TagZ struct {
|
||
|
Which air.Z_Which
|
||
|
Float64 float64 `capnp:"f64"`
|
||
|
I64 int64 `capnp:"-"`
|
||
|
U8 bool `capnp:"bool"`
|
||
|
}
|
||
|
|
||
|
func TestExtract_Tags(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
z Z
|
||
|
tagz TagZ
|
||
|
}{
|
||
|
{
|
||
|
name: "renamed field",
|
||
|
z: Z{Which: air.Z_Which_f64, F64: 3.5},
|
||
|
tagz: TagZ{Which: air.Z_Which_f64, Float64: 3.5},
|
||
|
},
|
||
|
{
|
||
|
name: "omitted field",
|
||
|
z: Z{Which: air.Z_Which_i64, I64: 42},
|
||
|
tagz: TagZ{Which: air.Z_Which_i64},
|
||
|
},
|
||
|
{
|
||
|
name: "field with overlapping name",
|
||
|
z: Z{Which: air.Z_Which_bool, Bool: true},
|
||
|
tagz: TagZ{Which: air.Z_Which_bool, U8: true},
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: NewMessage: %v", test.name, err)
|
||
|
continue
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: NewRootZ: %v", test.name, err)
|
||
|
continue
|
||
|
}
|
||
|
if err := zfill(z, &test.z); err != nil {
|
||
|
t.Errorf("%s: zfill: %v", test.name, err)
|
||
|
continue
|
||
|
}
|
||
|
out := new(TagZ)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("%s: Extract error: %v", test.name, err)
|
||
|
}
|
||
|
if *out != test.tagz {
|
||
|
t.Errorf("%s: Extract produced %s; want %s", test.name, zpretty.Sprint(out), zpretty.Sprint(test.tagz))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_Tags(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
tagz TagZ
|
||
|
z Z
|
||
|
}{
|
||
|
{
|
||
|
name: "renamed field",
|
||
|
tagz: TagZ{Which: air.Z_Which_f64, Float64: 3.5},
|
||
|
z: Z{Which: air.Z_Which_f64, F64: 3.5},
|
||
|
},
|
||
|
{
|
||
|
name: "omitted field",
|
||
|
tagz: TagZ{Which: air.Z_Which_i64, I64: 42},
|
||
|
z: Z{Which: air.Z_Which_i64, I64: 0},
|
||
|
},
|
||
|
{
|
||
|
name: "field with overlapping name",
|
||
|
tagz: TagZ{Which: air.Z_Which_bool, U8: true},
|
||
|
z: Z{Which: air.Z_Which_bool, Bool: true},
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: NewMessage: %v", test.name, err)
|
||
|
continue
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: NewRootZ: %v", test.name, err)
|
||
|
continue
|
||
|
}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, &test.tagz)
|
||
|
if err != nil {
|
||
|
t.Errorf("%s: Insert(%s) error: %v", test.name, zpretty.Sprint(test.tagz), err)
|
||
|
}
|
||
|
if equal, err := zequal(&test.z, z); err != nil {
|
||
|
t.Errorf("%s: Insert(%s) compare err: %v", test.name, zpretty.Sprint(test.tagz), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("%s: Insert(%s) produced %v", test.name, zpretty.Sprint(test.tagz), z)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type ZBool struct {
|
||
|
Which struct{} `capnp:",which=bool"`
|
||
|
Bool bool
|
||
|
}
|
||
|
|
||
|
func TestExtract_WhichTag(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
if err := zfill(z, &Z{Which: air.Z_Which_bool, Bool: true}); err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(ZBool)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err != nil {
|
||
|
t.Errorf("Extract error: %v", err)
|
||
|
}
|
||
|
if !out.Bool {
|
||
|
t.Errorf("Extract produced %s; want %s", zpretty.Sprint(out), zpretty.Sprint(&ZBool{Bool: true}))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestExtract_WhichTagMismatch(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
if err := zfill(z, &Z{Which: air.Z_Which_i64, I64: 42}); err != nil {
|
||
|
t.Fatalf("zfill: %v", err)
|
||
|
}
|
||
|
out := new(ZBool)
|
||
|
if err := Extract(out, air.Z_TypeID, z.Struct); err == nil {
|
||
|
t.Error("Extract did not return an error")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsert_WhichTag(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
zb := &ZBool{Bool: true}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, zb)
|
||
|
if err != nil {
|
||
|
t.Errorf("Insert(%s) error: %v", zpretty.Sprint(zb), err)
|
||
|
}
|
||
|
want := &Z{Which: air.Z_Which_bool, Bool: true}
|
||
|
if equal, err := zequal(want, z); err != nil {
|
||
|
t.Errorf("Insert(%s) compare err: %v", zpretty.Sprint(zb), err)
|
||
|
} else if !equal {
|
||
|
t.Errorf("Insert(%s) produced %v", zpretty.Sprint(zb), z)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type ZBoolWithExtra struct {
|
||
|
Which struct{} `capnp:",which=bool"`
|
||
|
Bool bool
|
||
|
ExtraField uint16
|
||
|
}
|
||
|
|
||
|
func TestExtraFields(t *testing.T) {
|
||
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewMessage: %v", err)
|
||
|
}
|
||
|
z, err := air.NewRootZ(seg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("NewRootZ: %v", err)
|
||
|
}
|
||
|
zb := &ZBoolWithExtra{Bool: true, ExtraField: 42}
|
||
|
err = Insert(air.Z_TypeID, z.Struct, zb)
|
||
|
if err == nil {
|
||
|
t.Errorf("Insert(%s) did not return error", zpretty.Sprint(zb))
|
||
|
}
|
||
|
err = Extract(zb, air.Z_TypeID, z.Struct)
|
||
|
if err == nil {
|
||
|
t.Errorf("Extract(%v) did not return error", z)
|
||
|
}
|
||
|
if zb.ExtraField != 42 {
|
||
|
t.Errorf("zb.ExtraField modified to %d; want 42", zb.ExtraField)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func zequal(g *Z, c air.Z) (bool, error) {
|
||
|
if g.Which != c.Which() {
|
||
|
return false, nil
|
||
|
}
|
||
|
listeq := func(has bool, n int, l capnp.List, f func(i int) (bool, error)) (bool, error) {
|
||
|
if has != l.IsValid() {
|
||
|
return false, nil
|
||
|
}
|
||
|
if !has {
|
||
|
return true, nil
|
||
|
}
|
||
|
if l.Len() != n {
|
||
|
return false, nil
|
||
|
}
|
||
|
for i := 0; i < l.Len(); i++ {
|
||
|
if ok, err := f(i); !ok || err != nil {
|
||
|
return ok, err
|
||
|
}
|
||
|
}
|
||
|
return true, nil
|
||
|
}
|
||
|
switch g.Which {
|
||
|
case air.Z_Which_f64:
|
||
|
return g.F64 == c.F64(), nil
|
||
|
case air.Z_Which_f32:
|
||
|
return g.F32 == c.F32(), nil
|
||
|
case air.Z_Which_i64:
|
||
|
return g.I64 == c.I64(), nil
|
||
|
case air.Z_Which_i32:
|
||
|
return g.I32 == c.I32(), nil
|
||
|
case air.Z_Which_i16:
|
||
|
return g.I16 == c.I16(), nil
|
||
|
case air.Z_Which_i8:
|
||
|
return g.I8 == c.I8(), nil
|
||
|
case air.Z_Which_u64:
|
||
|
return g.U64 == c.U64(), nil
|
||
|
case air.Z_Which_u32:
|
||
|
return g.U32 == c.U32(), nil
|
||
|
case air.Z_Which_u16:
|
||
|
return g.U16 == c.U16(), nil
|
||
|
case air.Z_Which_u8:
|
||
|
return g.U8 == c.U8(), nil
|
||
|
case air.Z_Which_bool:
|
||
|
return g.Bool == c.Bool(), nil
|
||
|
case air.Z_Which_text:
|
||
|
text, err := c.Text()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return g.Text == text, nil
|
||
|
case air.Z_Which_blob:
|
||
|
blob, err := c.Blob()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
if (blob == nil) != (g.Blob == nil) {
|
||
|
return false, nil
|
||
|
}
|
||
|
return bytes.Equal(g.Blob, blob), nil
|
||
|
case air.Z_Which_f64vec:
|
||
|
fv, err := c.F64vec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.F64vec != nil, len(g.F64vec), fv.List, func(i int) (bool, error) {
|
||
|
return fv.At(i) == g.F64vec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_f32vec:
|
||
|
fv, err := c.F32vec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.F32vec != nil, len(g.F32vec), fv.List, func(i int) (bool, error) {
|
||
|
return fv.At(i) == g.F32vec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_i64vec:
|
||
|
iv, err := c.I64vec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.I64vec != nil, len(g.I64vec), iv.List, func(i int) (bool, error) {
|
||
|
return iv.At(i) == g.I64vec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_i8vec:
|
||
|
iv, err := c.I8vec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.I8vec != nil, len(g.I8vec), iv.List, func(i int) (bool, error) {
|
||
|
return iv.At(i) == g.I8vec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_u64vec:
|
||
|
uv, err := c.U64vec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.U64vec != nil, len(g.U64vec), uv.List, func(i int) (bool, error) {
|
||
|
return uv.At(i) == g.U64vec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_u8vec:
|
||
|
uv, err := c.U8vec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.U8vec != nil, len(g.U8vec), uv.List, func(i int) (bool, error) {
|
||
|
return uv.At(i) == g.U8vec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_boolvec:
|
||
|
bv, err := c.Boolvec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.Boolvec != nil, len(g.Boolvec), bv.List, func(i int) (bool, error) {
|
||
|
return bv.At(i) == g.Boolvec[i], nil
|
||
|
})
|
||
|
case air.Z_Which_datavec:
|
||
|
dv, err := c.Datavec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.Datavec != nil, len(g.Datavec), dv.List, func(i int) (bool, error) {
|
||
|
di, err := dv.At(i)
|
||
|
return bytes.Equal(di, g.Datavec[i]), err
|
||
|
})
|
||
|
case air.Z_Which_textvec:
|
||
|
tv, err := c.Textvec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.Textvec != nil, len(g.Textvec), tv.List, func(i int) (bool, error) {
|
||
|
s, err := tv.At(i)
|
||
|
return s == g.Textvec[i], err
|
||
|
})
|
||
|
case air.Z_Which_zvec:
|
||
|
vec, err := c.Zvec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.Zvec != nil, len(g.Zvec), vec.List, func(i int) (bool, error) {
|
||
|
return zequal(g.Zvec[i], vec.At(i))
|
||
|
})
|
||
|
case air.Z_Which_zvecvec:
|
||
|
vv, err := c.Zvecvec()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.Zvecvec != nil, len(g.Zvecvec), vv.List, func(i int) (bool, error) {
|
||
|
p, err := vv.PtrAt(i)
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
v := air.Z_List{List: p.List()}
|
||
|
return listeq(g.Zvecvec[i] != nil, len(g.Zvecvec[i]), v.List, func(j int) (bool, error) {
|
||
|
return zequal(g.Zvecvec[i][j], v.At(j))
|
||
|
})
|
||
|
})
|
||
|
case air.Z_Which_planebase:
|
||
|
pb, err := c.Planebase()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
if (g.Planebase != nil) != pb.IsValid() {
|
||
|
return false, nil
|
||
|
}
|
||
|
if g.Planebase == nil {
|
||
|
return true, nil
|
||
|
}
|
||
|
name, err := pb.Name()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
if g.Planebase.Name != name {
|
||
|
return false, nil
|
||
|
}
|
||
|
homes, err := pb.Homes()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
homeseq, _ := listeq(g.Planebase.Homes != nil, len(g.Planebase.Homes), homes.List, func(i int) (bool, error) {
|
||
|
return g.Planebase.Homes[i] == homes.At(i), nil
|
||
|
})
|
||
|
if !homeseq {
|
||
|
return false, nil
|
||
|
}
|
||
|
return g.Planebase.Rating == pb.Rating() && g.Planebase.CanFly == pb.CanFly() && g.Planebase.Capacity == pb.Capacity() && g.Planebase.MaxSpeed == pb.MaxSpeed(), nil
|
||
|
case air.Z_Which_airport:
|
||
|
return g.Airport == c.Airport(), nil
|
||
|
case air.Z_Which_grp:
|
||
|
if g.Grp == nil {
|
||
|
return false, nil
|
||
|
}
|
||
|
return g.Grp.First == c.Grp().First() && g.Grp.Second == c.Grp().Second(), nil
|
||
|
case air.Z_Which_echo:
|
||
|
return g.Echo.Client == nil && !c.HasEcho() ||
|
||
|
g.Echo.Client != nil && c.HasEcho(), nil
|
||
|
case air.Z_Which_echoBases:
|
||
|
echoBases, err := c.EchoBases()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
list, err := echoBases.Bases()
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
return listeq(g.EchoBases.Bases != nil, len(g.EchoBases.Bases), list.List, func(i int) (bool, error) {
|
||
|
return (g.EchoBases.Bases[i].Echo.Client == nil) == !list.At(i).HasEcho(), nil
|
||
|
})
|
||
|
default:
|
||
|
return false, fmt.Errorf("zequal: unknown type: %v", g.Which)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (z *Z) equal(y *Z) bool {
|
||
|
if z.Which != y.Which {
|
||
|
return false
|
||
|
}
|
||
|
switch z.Which {
|
||
|
case air.Z_Which_f64:
|
||
|
return z.F64 == y.F64
|
||
|
case air.Z_Which_f32:
|
||
|
return z.F32 == y.F32
|
||
|
case air.Z_Which_i64:
|
||
|
return z.I64 == y.I64
|
||
|
case air.Z_Which_i32:
|
||
|
return z.I32 == y.I32
|
||
|
case air.Z_Which_i16:
|
||
|
return z.I16 == y.I16
|
||
|
case air.Z_Which_i8:
|
||
|
return z.I8 == y.I8
|
||
|
case air.Z_Which_u64:
|
||
|
return z.U64 == y.U64
|
||
|
case air.Z_Which_u32:
|
||
|
return z.U32 == y.U32
|
||
|
case air.Z_Which_u16:
|
||
|
return z.U16 == y.U16
|
||
|
case air.Z_Which_u8:
|
||
|
return z.U8 == y.U8
|
||
|
case air.Z_Which_bool:
|
||
|
return z.Bool == y.Bool
|
||
|
case air.Z_Which_text:
|
||
|
return z.Text == y.Text
|
||
|
case air.Z_Which_blob:
|
||
|
return bytes.Equal(z.Blob, y.Blob)
|
||
|
case air.Z_Which_f64vec:
|
||
|
return sliceeq(len(z.F64vec), len(y.F64vec), func(i int) bool {
|
||
|
return z.F64vec[i] == y.F64vec[i]
|
||
|
})
|
||
|
case air.Z_Which_f32vec:
|
||
|
return sliceeq(len(z.F32vec), len(y.F32vec), func(i int) bool {
|
||
|
return z.F32vec[i] == y.F32vec[i]
|
||
|
})
|
||
|
case air.Z_Which_i64vec:
|
||
|
return sliceeq(len(z.I64vec), len(y.I64vec), func(i int) bool {
|
||
|
return z.I64vec[i] == y.I64vec[i]
|
||
|
})
|
||
|
case air.Z_Which_i8vec:
|
||
|
return sliceeq(len(z.I8vec), len(y.I8vec), func(i int) bool {
|
||
|
return z.I8vec[i] == y.I8vec[i]
|
||
|
})
|
||
|
case air.Z_Which_u64vec:
|
||
|
return sliceeq(len(z.U64vec), len(y.U64vec), func(i int) bool {
|
||
|
return z.U64vec[i] == y.U64vec[i]
|
||
|
})
|
||
|
case air.Z_Which_u8vec:
|
||
|
return sliceeq(len(z.U8vec), len(y.U8vec), func(i int) bool {
|
||
|
return z.U8vec[i] == y.U8vec[i]
|
||
|
})
|
||
|
case air.Z_Which_boolvec:
|
||
|
return sliceeq(len(z.Boolvec), len(y.Boolvec), func(i int) bool {
|
||
|
return z.Boolvec[i] == y.Boolvec[i]
|
||
|
})
|
||
|
case air.Z_Which_datavec:
|
||
|
return sliceeq(len(z.Datavec), len(y.Datavec), func(i int) bool {
|
||
|
return bytes.Equal(z.Datavec[i], y.Datavec[i])
|
||
|
})
|
||
|
case air.Z_Which_textvec:
|
||
|
return sliceeq(len(z.Textvec), len(y.Textvec), func(i int) bool {
|
||
|
return z.Textvec[i] == y.Textvec[i]
|
||
|
})
|
||
|
case air.Z_Which_zvec:
|
||
|
return sliceeq(len(z.Zvec), len(y.Zvec), func(i int) bool {
|
||
|
return z.Zvec[i].equal(y.Zvec[i])
|
||
|
})
|
||
|
case air.Z_Which_zvecvec:
|
||
|
return sliceeq(len(z.Zvecvec), len(y.Zvecvec), func(i int) bool {
|
||
|
return sliceeq(len(z.Zvecvec[i]), len(y.Zvecvec[i]), func(j int) bool {
|
||
|
return z.Zvecvec[i][j].equal(y.Zvecvec[i][j])
|
||
|
})
|
||
|
})
|
||
|
case air.Z_Which_planebase:
|
||
|
return z.Planebase.equal(y.Planebase)
|
||
|
case air.Z_Which_airport:
|
||
|
return z.Airport == y.Airport
|
||
|
case air.Z_Which_grp:
|
||
|
return z.Grp.First == y.Grp.First && z.Grp.Second == y.Grp.Second
|
||
|
case air.Z_Which_echo:
|
||
|
return (z.Echo.Client == nil) == (y.Echo.Client == nil)
|
||
|
case air.Z_Which_echoBases:
|
||
|
return sliceeq(len(z.EchoBases.Bases), len(y.EchoBases.Bases), func(i int) bool {
|
||
|
return (z.EchoBases.Bases[i].Echo.Client == nil) ==
|
||
|
(y.EchoBases.Bases[i].Echo.Client == nil)
|
||
|
})
|
||
|
default:
|
||
|
panic("unknown Z which")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func zfill(c air.Z, g *Z) error {
|
||
|
switch g.Which {
|
||
|
case air.Z_Which_f64:
|
||
|
c.SetF64(g.F64)
|
||
|
case air.Z_Which_f32:
|
||
|
c.SetF32(g.F32)
|
||
|
case air.Z_Which_i64:
|
||
|
c.SetI64(g.I64)
|
||
|
case air.Z_Which_i32:
|
||
|
c.SetI32(g.I32)
|
||
|
case air.Z_Which_i16:
|
||
|
c.SetI16(g.I16)
|
||
|
case air.Z_Which_i8:
|
||
|
c.SetI8(g.I8)
|
||
|
case air.Z_Which_u64:
|
||
|
c.SetU64(g.U64)
|
||
|
case air.Z_Which_u32:
|
||
|
c.SetU32(g.U32)
|
||
|
case air.Z_Which_u16:
|
||
|
c.SetU16(g.U16)
|
||
|
case air.Z_Which_u8:
|
||
|
c.SetU8(g.U8)
|
||
|
case air.Z_Which_bool:
|
||
|
c.SetBool(g.Bool)
|
||
|
case air.Z_Which_text:
|
||
|
return c.SetText(g.Text)
|
||
|
case air.Z_Which_blob:
|
||
|
return c.SetBlob(g.Blob)
|
||
|
case air.Z_Which_f64vec:
|
||
|
if g.F64vec == nil {
|
||
|
return c.SetF64vec(capnp.Float64List{})
|
||
|
}
|
||
|
fv, err := c.NewF64vec(int32(len(g.F64vec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, f := range g.F64vec {
|
||
|
fv.Set(i, f)
|
||
|
}
|
||
|
case air.Z_Which_f32vec:
|
||
|
if g.F32vec == nil {
|
||
|
return c.SetF32vec(capnp.Float32List{})
|
||
|
}
|
||
|
fv, err := c.NewF32vec(int32(len(g.F32vec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, f := range g.F32vec {
|
||
|
fv.Set(i, f)
|
||
|
}
|
||
|
case air.Z_Which_i64vec:
|
||
|
if g.I64vec == nil {
|
||
|
return c.SetI64vec(capnp.Int64List{})
|
||
|
}
|
||
|
iv, err := c.NewI64vec(int32(len(g.I64vec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, n := range g.I64vec {
|
||
|
iv.Set(i, n)
|
||
|
}
|
||
|
case air.Z_Which_i8vec:
|
||
|
if g.I8vec == nil {
|
||
|
return c.SetI8vec(capnp.Int8List{})
|
||
|
}
|
||
|
iv, err := c.NewI8vec(int32(len(g.I8vec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, n := range g.I8vec {
|
||
|
iv.Set(i, n)
|
||
|
}
|
||
|
case air.Z_Which_u64vec:
|
||
|
if g.U64vec == nil {
|
||
|
return c.SetU64vec(capnp.UInt64List{})
|
||
|
}
|
||
|
uv, err := c.NewU64vec(int32(len(g.U64vec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, n := range g.U64vec {
|
||
|
uv.Set(i, n)
|
||
|
}
|
||
|
case air.Z_Which_u8vec:
|
||
|
if g.U8vec == nil {
|
||
|
return c.SetU8vec(capnp.UInt8List{})
|
||
|
}
|
||
|
uv, err := c.NewU8vec(int32(len(g.U8vec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, n := range g.U8vec {
|
||
|
uv.Set(i, n)
|
||
|
}
|
||
|
case air.Z_Which_boolvec:
|
||
|
if g.Boolvec == nil {
|
||
|
return c.SetBoolvec(capnp.BitList{})
|
||
|
}
|
||
|
vec, err := c.NewBoolvec(int32(len(g.Boolvec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, v := range g.Boolvec {
|
||
|
vec.Set(i, v)
|
||
|
}
|
||
|
case air.Z_Which_datavec:
|
||
|
if g.Datavec == nil {
|
||
|
return c.SetDatavec(capnp.DataList{})
|
||
|
}
|
||
|
vec, err := c.NewDatavec(int32(len(g.Datavec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, v := range g.Datavec {
|
||
|
if err := vec.Set(i, v); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
case air.Z_Which_textvec:
|
||
|
if g.Textvec == nil {
|
||
|
return c.SetTextvec(capnp.TextList{})
|
||
|
}
|
||
|
vec, err := c.NewTextvec(int32(len(g.Textvec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, v := range g.Textvec {
|
||
|
if err := vec.Set(i, v); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
case air.Z_Which_zvec:
|
||
|
if g.Zvec == nil {
|
||
|
return c.SetZvec(air.Z_List{})
|
||
|
}
|
||
|
vec, err := c.NewZvec(int32(len(g.Zvec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, z := range g.Zvec {
|
||
|
if err := zfill(vec.At(i), z); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
case air.Z_Which_zvecvec:
|
||
|
if g.Zvecvec == nil {
|
||
|
return c.SetZvecvec(capnp.PointerList{})
|
||
|
}
|
||
|
vv, err := c.NewZvecvec(int32(len(g.Zvecvec)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, zz := range g.Zvecvec {
|
||
|
v, err := air.NewZ_List(vv.Segment(), int32(len(zz)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := vv.SetPtr(i, v.ToPtr()); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for j, z := range zz {
|
||
|
if err := zfill(v.At(j), z); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
case air.Z_Which_planebase:
|
||
|
if g.Planebase == nil {
|
||
|
return c.SetPlanebase(air.PlaneBase{})
|
||
|
}
|
||
|
pb, err := c.NewPlanebase()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := pb.SetName(g.Planebase.Name); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if g.Planebase.Homes != nil {
|
||
|
homes, err := pb.NewHomes(int32(len(g.Planebase.Homes)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i := range g.Planebase.Homes {
|
||
|
homes.Set(i, g.Planebase.Homes[i])
|
||
|
}
|
||
|
}
|
||
|
pb.SetRating(g.Planebase.Rating)
|
||
|
pb.SetCanFly(g.Planebase.CanFly)
|
||
|
pb.SetCapacity(g.Planebase.Capacity)
|
||
|
pb.SetMaxSpeed(g.Planebase.MaxSpeed)
|
||
|
case air.Z_Which_airport:
|
||
|
c.SetAirport(g.Airport)
|
||
|
case air.Z_Which_grp:
|
||
|
c.SetGrp()
|
||
|
if g.Grp != nil {
|
||
|
c.Grp().SetFirst(g.Grp.First)
|
||
|
c.Grp().SetSecond(g.Grp.Second)
|
||
|
}
|
||
|
case air.Z_Which_echo:
|
||
|
c.SetEcho(g.Echo)
|
||
|
case air.Z_Which_echoBases:
|
||
|
echoBases, err := c.NewEchoBases()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
list, err := echoBases.NewBases(int32(len(g.EchoBases.Bases)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for i, v := range g.EchoBases.Bases {
|
||
|
base := list.At(i)
|
||
|
base.SetEcho(v.Echo)
|
||
|
}
|
||
|
default:
|
||
|
return fmt.Errorf("zfill: unknown type: %v", g.Which)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var zpretty = &pretty.Config{
|
||
|
Compact: true,
|
||
|
SkipZeroFields: true,
|
||
|
}
|
||
|
|
||
|
func sliceeq(na, nb int, f func(i int) bool) bool {
|
||
|
if na != nb {
|
||
|
return false
|
||
|
}
|
||
|
for i := 0; i < na; i++ {
|
||
|
if !f(i) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|