diff options
Diffstat (limited to 'codec/marshaler_test.go')
-rw-r--r-- | codec/marshaler_test.go | 712 |
1 files changed, 712 insertions, 0 deletions
diff --git a/codec/marshaler_test.go b/codec/marshaler_test.go new file mode 100644 index 0000000..9a1887b --- /dev/null +++ b/codec/marshaler_test.go @@ -0,0 +1,712 @@ +// Copyright (c) 2020 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package codec_test + +import ( + "bytes" + "encoding/binary" + "reflect" + "testing" + + "github.com/lunixbochs/struc" + + "git.fd.io/govpp.git/api" + "git.fd.io/govpp.git/codec" + "git.fd.io/govpp.git/examples/binapi/fib_types" + "git.fd.io/govpp.git/examples/binapi/interface_types" + "git.fd.io/govpp.git/examples/binapi/interfaces" + "git.fd.io/govpp.git/examples/binapi/ip" + "git.fd.io/govpp.git/examples/binapi/ip_types" + "git.fd.io/govpp.git/examples/binapi/sr" +) + +/*func TestNewCodecEncodeDecode(t *testing.T) { + tests := []struct { + name string + msg Codec + }{ + { + "", &TestAllMsg{ + Bool: true, + AliasUint32: 5, + AliasArray: MacAddress{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}, + BaseArray: []uint32{0x00, 0x00, 0x00, 0x00}, + Enum: IF_STATUS_API_FLAG_LINK_UP, + Uint8: 8, + Uint16: 16, + Uint32: 32, + Int8: 88, + Int16: 1616, + Int32: 3232, + Slice: []byte{10, 20, 30, 40, 0, 0, 0}, + String: "abcdefghikl", + SizeOf: 2, + VariableSlice: []SliceType{ + {Proto: IP_API_PROTO_AH}, + {Proto: IP_API_PROTO_ESP}, + }, + TypeUnion: Address{ + Af: ADDRESS_IP4, + Un: AddressUnionIP4(IP4Address{1, 2, 3, 4}), + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + data, err := test.msg.Marshal() + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + var m2 TestAllMsg + if err := m2.Unmarshal(data); err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("Data:\nOLD: %+v\nNEW: %+v", m, &m2) + + if !reflect.DeepEqual(m, &m2) { + t.Fatalf("newData differs from oldData") + } + }) + } +}*/ + +func NewTestAllMsg() *TestAllMsg { + return &TestAllMsg{ + Bool: true, + AliasUint32: 5, + AliasArray: MacAddress{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}, + BaseArray: []uint32{0x00, 0x00, 0x00, 0x00}, + Enum: IF_STATUS_API_FLAG_LINK_UP, + Uint8: 8, + Uint16: 16, + Uint32: 32, + Int8: 88, + Int16: 1616, + Int32: 3232, + Slice: []byte{10, 20, 30, 40, 0, 0, 0}, + String: "abcdefghikl", + SizeOf: 2, + VariableSlice: []SliceType{ + {Proto: IP_API_PROTO_AH}, + {Proto: IP_API_PROTO_ESP}, + }, + TypeUnion: Address{ + Af: ADDRESS_IP4, + Un: AddressUnionIP4(IP4Address{1, 2, 3, 4}), + }, + } +} + +func TestNewCodecEncodeDecode_(t *testing.T) { + m := NewTestAllMsg() + + data, err := m.Marshal(nil) + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + var m2 TestAllMsg + if err := m2.Unmarshal(data); err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("Data:\nOLD: %+v\nNEW: %+v", m, &m2) + + if !reflect.DeepEqual(m, &m2) { + t.Fatalf("newData differs from oldData") + } +} + +// ------------- + +func TestNewCodecEncodeDecode3(t *testing.T) { + m := NewTestAllMsg() + data, err := m.Marshal(nil) + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + var m2 TestAllMsg + if err := m2.Unmarshal(data); err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("Data:\nOLD: %+v\nNEW: %+v", m, &m2) + + if !reflect.DeepEqual(m, &m2) { + t.Fatalf("newData differs from oldData") + } +} +func TestNewCodecEncodeDecode4(t *testing.T) { + m := &interfaces.SwInterfaceSetRxMode{ + Mode: interface_types.RX_MODE_API_POLLING, + QueueID: 70000, + QueueIDValid: true, + SwIfIndex: 300, + } + + b := make([]byte, 2+m.Size()) + + data, err := m.Marshal(b[2:]) + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("ENCODED DATA(%d): % 03x", len(data), data) + + var m2 interfaces.SwInterfaceSetRxMode + if err := m2.Unmarshal(b[2:]); err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("Data:\nOLD: %+v\nNEW: %+v", m, &m2) + + if !reflect.DeepEqual(m, &m2) { + t.Fatalf("newData differs from oldData") + } +} +func TestNewCodecEncodeDecode2(t *testing.T) { + m := &sr.SrPoliciesDetails{ + Bsid: sr.IP6Address{00, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, + IsSpray: true, + IsEncap: false, + FibTable: 33, + NumSidLists: 1, + SidLists: []sr.Srv6SidList{ + { + Weight: 555, + NumSids: 2, + Sids: [16]sr.IP6Address{ + {99}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + }, + }, + }, + } + + b := make([]byte, 0, m.Size()) + data, err := m.Marshal(b) + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("ENCODED DATA(%d): % 03x", len(data), data) + + var m2 sr.SrPoliciesDetails + if err := m2.Unmarshal(data); err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + + t.Logf("Data:\nOLD: %+v\nNEW: %+v", m, &m2) + + if !reflect.DeepEqual(m, &m2) { + t.Fatalf("newData differs from oldData") + } +} + +func TestNewCodecEncode(t *testing.T) { + //m := NewIPRouteLookupReply() + m := &sr.SrPoliciesDetails{ + Bsid: sr.IP6Address{00, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, + IsSpray: true, + IsEncap: false, + FibTable: 33, + NumSidLists: 1, + SidLists: []sr.Srv6SidList{ + { + Weight: 555, + NumSids: 2, + Sids: [16]sr.IP6Address{ + {99}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + }, + }, + }, + } + + size := m.Size() + t.Logf("size: %d", size) + + var err error + var oldData, newData []byte + { + var c codec.OldCodec + oldData, err = c.Marshal(m) + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + } + { + newData, err = m.Marshal(nil) + if err != nil { + t.Fatalf("expected nil error, got: %v", err) + } + } + t.Logf("Data:\nOLD[%d]: % 03x\nNEW[%d]: % 03x", len(oldData), oldData, len(newData), newData) + + if !bytes.Equal(oldData, newData) { + t.Fatalf("newData differs from oldData") + } +} + +func TestNewCodecDecode(t *testing.T) { + /*m := &ip.IPRouteLookupReply{} + size := m.Size() + t.Logf("size: %d", size)*/ + data := []byte{ + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x09, 0x00, + 0x00, 0x00, 0x08, 0x07, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + } + + var err error + var oldData, newData ip.IPRouteLookupReply + { + var c codec.OldCodec + err = c.Unmarshal(data, &oldData) + if err != nil { + t.Errorf("expected nil error, got: %v", err) + } + } + { + err = newData.Unmarshal(data) + if err != nil { + t.Errorf("expected nil error, got: %v", err) + } + } + t.Logf("Data:\nOLD: %+v\nNEW: %+v", oldData, newData) + + if !reflect.DeepEqual(oldData, newData) { + t.Fatalf("newData differs from oldData") + } +} + +func NewIPRouteLookupReply() *ip.IPRouteLookupReply { + return &ip.IPRouteLookupReply{ + Retval: 1, + Route: ip.IPRoute{ + TableID: 3, + StatsIndex: 5, + Prefix: ip.Prefix{ + Address: ip_types.Address{ + Af: fib_types.ADDRESS_IP6, + Un: ip_types.AddressUnion{}, + }, + Len: 24, + }, + NPaths: 2, + Paths: []ip.FibPath{ + { + SwIfIndex: 5, + TableID: 6, + RpfID: 8, + Weight: 9, + Preference: 10, + Type: 11, + Flags: 1, + Proto: 2, + Nh: ip.FibPathNh{ + Address: ip.AddressUnion{}, + ViaLabel: 3, + ObjID: 1, + ClassifyTableIndex: 2, + }, + NLabels: 1, + LabelStack: [16]ip.FibMplsLabel{ + { + IsUniform: 9, + Label: 8, + TTL: 7, + Exp: 6, + }, + }, + }, + { + SwIfIndex: 7, + TableID: 6, + RpfID: 8, + Weight: 9, + Preference: 10, + Type: 11, + Flags: 1, + Proto: 1, + Nh: ip.FibPathNh{ + Address: ip.AddressUnion{}, + ViaLabel: 3, + ObjID: 1, + ClassifyTableIndex: 2, + }, + NLabels: 2, + LabelStack: [16]ip.FibMplsLabel{ + { + IsUniform: 9, + Label: 8, + TTL: 7, + Exp: 6, + }, + { + IsUniform: 10, + Label: 8, + TTL: 7, + Exp: 6, + }, + }, + }, + }, + }, + } +} + +func TestSize(t *testing.T) { + m := NewTestAllMsg() + size := binary.Size(*m) + t.Logf("size: %v", size) +} + +func (m *TestAllMsg) Marshal(b []byte) ([]byte, error) { + order := binary.BigEndian + tmp := make([]byte, 143) + pos := 0 + + tmp[pos] = boolToUint(m.Bool) + pos += 1 + + tmp[pos] = m.Uint8 + pos += 1 + + order.PutUint16(tmp[pos:pos+2], m.Uint16) + pos += 2 + + order.PutUint32(tmp[pos:pos+4], m.Uint32) + pos += 4 + + tmp[pos] = byte(m.Int8) + pos += 1 + + order.PutUint16(tmp[pos:pos+2], uint16(m.Int16)) + pos += 2 + + order.PutUint32(tmp[pos:pos+4], uint32(m.Int32)) + pos += 4 + + order.PutUint32(tmp[pos:pos+4], uint32(m.AliasUint32)) + pos += 4 + + copy(tmp[pos:pos+6], m.AliasArray[:]) + pos += 6 + + order.PutUint32(tmp[pos:pos+4], uint32(m.Enum)) + pos += 4 + + for i := 0; i < 4; i++ { + var x uint32 + if i < len(m.BaseArray) { + x = m.BaseArray[i] + } + order.PutUint32(tmp[pos:pos+4], uint32(x)) + pos += 4 + } + + copy(tmp[pos:pos+7], m.Slice) + pos += 7 + + copy(tmp[pos:pos+64], m.String) + pos += 64 + + order.PutUint32(tmp[pos:pos+4], uint32(len(m.VlaStr)) /*m.SizeOf*/) + pos += 4 + + copy(tmp[pos:pos+len(m.VlaStr)], m.VlaStr[:]) + pos += len(m.VlaStr) + + order.PutUint32(tmp[pos:pos+4], uint32(len(m.VariableSlice)) /*m.SizeOf*/) + pos += 4 + + for i := range m.VariableSlice { + tmp[pos+i*1] = uint8(m.VariableSlice[i].Proto) + //copy(tmp[102+i:103+i], []byte{byte(m.VariableSlice[i].Proto)}) + } + pos += len(m.VariableSlice) * 1 + + tmp[pos] = uint8(m.TypeUnion.Af) + pos += 1 + + copy(tmp[pos:pos+16], m.TypeUnion.Un.XXX_UnionData[:]) + pos += 16 + + return tmp, nil + + /*_, err := buf.Write(tmp) + if err != nil { + return nil, err + } + return buf.Bytes(), nil*/ +} + +func (m *TestAllMsg) Unmarshal(tmp []byte) error { + order := binary.BigEndian + + //tmp := make([]byte, 143) + pos := 0 + + m.Bool = tmp[pos] != 0 + pos += 1 + + //tmp[pos] = m.Uint8 + m.Uint8 = tmp[pos] + pos += 1 + + //order.PutUint16(tmp[pos:pos+2], m.Uint16) + m.Uint16 = order.Uint16(tmp[pos : pos+2]) + pos += 2 + + //order.PutUint32(tmp[pos:pos+4], m.Uint32) + m.Uint32 = order.Uint32(tmp[pos : pos+4]) + pos += 4 + + //tmp[pos] = byte(m.Int8) + m.Int8 = int8(tmp[pos]) + pos += 1 + + //order.PutUint16(tmp[pos:pos+2], uint16(m.Int16)) + m.Int16 = int16(order.Uint16(tmp[pos : pos+2])) + pos += 2 + + //order.PutUint32(tmp[pos:pos+4], uint32(m.Int32)) + m.Int32 = int32(order.Uint32(tmp[pos : pos+4])) + pos += 4 + + //order.PutUint32(tmp[pos:pos+4], uint32(m.AliasUint32)) + m.AliasUint32 = InterfaceIndex(order.Uint32(tmp[pos : pos+4])) + pos += 4 + + //copy(tmp[pos:pos+6], m.AliasArray[:]) + copy(m.AliasArray[:], tmp[pos:pos+6]) + pos += 6 + + //order.PutUint32(tmp[pos:pos+4], uint32(m.Enum)) + m.Enum = IfStatusFlags(order.Uint32(tmp[pos : pos+4])) + pos += 4 + + m.BaseArray = make([]uint32, 4) + for i := 0; i < 4; i++ { + /*var x uint32 + if i < len(m.BaseArray) { + x = m.BaseArray[i] + } + order.PutUint32(tmp[pos:pos+4], uint32(x))*/ + m.BaseArray[i] = order.Uint32(tmp[pos : pos+4]) + pos += 4 + } + + m.Slice = make([]byte, 7) + copy(m.Slice[:7], tmp[pos:pos+7]) + //copy(tmp[pos:pos+7], m.Slice) + pos += 7 + + i := bytes.Index(tmp[pos:pos+64], []byte{0x00}) + m.String = string(tmp[pos : pos+i]) + //copy(tmp[pos:pos+64], m.String) + pos += 64 + + //order.PutUint32(tmp[pos:pos+4], uint32(len(m.VlaStr)) /*m.SizeOf*/) + VlaStrLen := int(order.Uint32(tmp[pos : pos+4])) + pos += 4 + + m.VlaStr = string(tmp[pos : pos+VlaStrLen]) + //copy(m.VlaStr[pos:pos+VlaStrLen], tmp[pos:pos+64]) + pos += len(m.VlaStr) + + m.SizeOf = uint32(order.Uint32(tmp[pos : pos+4])) + pos += 4 + + /*order.PutUint32(tmp[pos:pos+4], uint32(len(m.VariableSlice))) + m.VariableSlice = IfStatusFlags(order.Uint32(tmp[pos : pos+4])) + pos += 4*/ + + m.VariableSlice = make([]SliceType, m.SizeOf) + for i := range m.VariableSlice { + //tmp[pos+i*1] = uint8(m.VariableSlice[i].Proto) + m.VariableSlice[i].Proto = IPProto(tmp[pos+i*1]) + //copy(tmp[102+i:103+i], []byte{byte(m.VariableSlice[i].Proto)}) + } + pos += len(m.VariableSlice) * 1 + + //tmp[pos] = uint8(m.TypeUnion.Af) + m.TypeUnion.Af = AddressFamily(tmp[pos]) + pos += 1 + + //copy(tmp[pos:pos+16], m.TypeUnion.Un.XXX_UnionData[:]) + copy(m.TypeUnion.Un.XXX_UnionData[:], tmp[pos:pos+16]) + pos += 16 + + return nil + /*_, err := buf.Write(tmp) + if err != nil { + return nil, err + } + return buf.Bytes(), nil*/ +} + +func boolToUint(b bool) uint8 { + if b { + return 1 + } + return 0 +} + +// SwInterfaceDetails represents VPP binary API message 'sw_interface_details'. +type TestAllMsg struct { + Bool bool + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 + Int8 int8 + Int16 int16 + Int32 int32 + AliasUint32 InterfaceIndex + AliasArray MacAddress + Enum IfStatusFlags + BaseArray []uint32 `struc:"[4]uint32"` + Slice []byte `struc:"[7]byte"` + String string `struc:"[64]byte"` + XXX_VlaStrLen uint32 `struc:"sizeof=VlaStr"` + VlaStr string + SizeOf uint32 `struc:"sizeof=VariableSlice"` + VariableSlice []SliceType + TypeUnion Address +} + +type InterfaceIndex uint32 +type MacAddress [6]uint8 +type IfStatusFlags uint32 + +const ( + IF_STATUS_API_FLAG_ADMIN_UP IfStatusFlags = 1 + IF_STATUS_API_FLAG_LINK_UP IfStatusFlags = 2 +) + +// Address represents VPP binary API type 'address'. +type Address struct { + Af AddressFamily + Un AddressUnion +} + +// AddressFamily represents VPP binary API enum 'address_family'. +type AddressFamily uint8 + +const ( + ADDRESS_IP4 AddressFamily = 0 + ADDRESS_IP6 AddressFamily = 1 +) + +// AddressUnion represents VPP binary API union 'address_union'. +type AddressUnion struct { + XXX_UnionData [16]byte +} + +func (*AddressUnion) GetTypeName() string { return "address_union" } + +func AddressUnionIP4(a IP4Address) (u AddressUnion) { + u.SetIP4(a) + return +} +func (u *AddressUnion) SetIP4(a IP4Address) { + var b = new(bytes.Buffer) + if err := struc.Pack(b, &a); err != nil { + return + } + copy(u.XXX_UnionData[:], b.Bytes()) +} +func (u *AddressUnion) GetIP4() (a IP4Address) { + var b = bytes.NewReader(u.XXX_UnionData[:]) + struc.Unpack(b, &a) + return +} + +func AddressUnionIP6(a IP6Address) (u AddressUnion) { + u.SetIP6(a) + return +} +func (u *AddressUnion) SetIP6(a IP6Address) { + var b = new(bytes.Buffer) + if err := struc.Pack(b, &a); err != nil { + return + } + copy(u.XXX_UnionData[:], b.Bytes()) +} +func (u *AddressUnion) GetIP6() (a IP6Address) { + var b = bytes.NewReader(u.XXX_UnionData[:]) + struc.Unpack(b, &a) + return +} + +// IP4Address represents VPP binary API alias 'ip4_address'. +type IP4Address [4]uint8 + +// IP6Address represents VPP binary API alias 'ip6_address'. +type IP6Address [16]uint8 + +type SliceType struct { + Proto IPProto +} + +type IPProto uint8 + +const ( + IP_API_PROTO_HOPOPT IPProto = 0 + IP_API_PROTO_ICMP IPProto = 1 + IP_API_PROTO_IGMP IPProto = 2 + IP_API_PROTO_TCP IPProto = 6 + IP_API_PROTO_UDP IPProto = 17 + IP_API_PROTO_GRE IPProto = 47 + IP_API_PROTO_ESP IPProto = 50 + IP_API_PROTO_AH IPProto = 51 + IP_API_PROTO_ICMP6 IPProto = 58 + IP_API_PROTO_EIGRP IPProto = 88 + IP_API_PROTO_OSPF IPProto = 89 + IP_API_PROTO_SCTP IPProto = 132 + IP_API_PROTO_RESERVED IPProto = 255 +) + +func (m *TestAllMsg) Reset() { *m = TestAllMsg{} } +func (*TestAllMsg) GetMessageName() string { return "sw_interface_details" } +func (*TestAllMsg) GetCrcString() string { return "17b69fa2" } +func (*TestAllMsg) GetMessageType() api.MessageType { return api.ReplyMessage } |