143 lines
4.2 KiB
Go
143 lines
4.2 KiB
Go
package binaryutil
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"reflect"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
func TestNativeByteOrder(t *testing.T) {
|
|
// See https://stackoverflow.com/a/53286786
|
|
var natEnd binary.ByteOrder
|
|
|
|
canary := [2]byte{}
|
|
*(*uint16)(unsafe.Pointer(&canary[0])) = uint16(0xABCD)
|
|
|
|
switch canary {
|
|
case [2]byte{0xCD, 0xAB}:
|
|
natEnd = binary.LittleEndian
|
|
case [2]byte{0xAB, 0xCD}:
|
|
natEnd = binary.BigEndian
|
|
default:
|
|
t.Fatalf("unsupported \"mixed\" native endianness")
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
expectedv interface{}
|
|
marshal func(v interface{}) []byte
|
|
unmarshal func(b []byte) interface{}
|
|
reference func(v interface{}, b []byte)
|
|
}{
|
|
{
|
|
name: "Uint16",
|
|
expectedv: uint16(0x1234),
|
|
marshal: func(v interface{}) []byte { return NativeEndian.PutUint16(v.(uint16)) },
|
|
unmarshal: func(b []byte) interface{} { return NativeEndian.Uint16(b) },
|
|
reference: func(v interface{}, b []byte) { natEnd.PutUint16(b, v.(uint16)) },
|
|
},
|
|
{
|
|
name: "Uint32",
|
|
expectedv: uint32(0x12345678),
|
|
marshal: func(v interface{}) []byte { return NativeEndian.PutUint32(v.(uint32)) },
|
|
unmarshal: func(b []byte) interface{} { return NativeEndian.Uint32(b) },
|
|
reference: func(v interface{}, b []byte) { natEnd.PutUint32(b, v.(uint32)) },
|
|
},
|
|
{
|
|
name: "Uint64",
|
|
expectedv: uint64(0x1234567801020304),
|
|
marshal: func(v interface{}) []byte { return NativeEndian.PutUint64(v.(uint64)) },
|
|
unmarshal: func(b []byte) interface{} { return NativeEndian.Uint64(b) },
|
|
reference: func(v interface{}, b []byte) { natEnd.PutUint64(b, v.(uint64)) },
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
expectedb := make([]byte, reflect.TypeOf(tt.expectedv).Size())
|
|
tt.reference(tt.expectedv, expectedb)
|
|
actualb := tt.marshal(tt.expectedv)
|
|
if !bytes.Equal(actualb, expectedb) {
|
|
t.Errorf("NativeEndian.Put%s failure, expected: %#v, got: %#v", tt.name, expectedb, actualb)
|
|
}
|
|
actualv := tt.unmarshal(actualb)
|
|
if !reflect.DeepEqual(tt.expectedv, actualv) {
|
|
t.Errorf("NativeEndian.%s failure, expected: %#v, got: %#v", tt.name, tt.expectedv, actualv)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBigEndian(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
expected []byte
|
|
expectedv interface{}
|
|
actual []byte
|
|
unmarshal func(b []byte) interface{}
|
|
}{
|
|
{
|
|
name: "Uint16",
|
|
expected: []byte{0x12, 0x34},
|
|
expectedv: uint16(0x1234),
|
|
actual: BigEndian.PutUint16(0x1234),
|
|
unmarshal: func(b []byte) interface{} { return BigEndian.Uint16(b) },
|
|
},
|
|
{
|
|
name: "Uint32",
|
|
expected: []byte{0x12, 0x34, 0x56, 0x78},
|
|
expectedv: uint32(0x12345678),
|
|
actual: BigEndian.PutUint32(0x12345678),
|
|
unmarshal: func(b []byte) interface{} { return BigEndian.Uint32(b) },
|
|
},
|
|
{
|
|
name: "Uint64",
|
|
expected: []byte{0x12, 0x34, 0x56, 0x78, 0x01, 0x02, 0x03, 0x04},
|
|
expectedv: uint64(0x1234567801020304),
|
|
actual: BigEndian.PutUint64(0x1234567801020304),
|
|
unmarshal: func(b []byte) interface{} { return BigEndian.Uint64(b) },
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
if bytes.Compare(tt.actual, tt.expected) != 0 {
|
|
t.Errorf("BigEndian.Put%s failure, expected: %#v, got: %#v", tt.name, tt.expected, tt.actual)
|
|
}
|
|
if actual := tt.unmarshal(tt.actual); !reflect.DeepEqual(actual, tt.expectedv) {
|
|
t.Errorf("BigEndian.%s failure, expected: %#v, got: %#v", tt.name, tt.expectedv, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOtherTypes(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
expected []byte
|
|
expectedv interface{}
|
|
actual []byte
|
|
unmarshal func(b []byte) interface{}
|
|
}{
|
|
{
|
|
name: "Int32",
|
|
expected: []byte{0x78, 0x56, 0x34, 0x12},
|
|
expectedv: int32(0x12345678),
|
|
actual: PutInt32(0x12345678),
|
|
unmarshal: func(b []byte) interface{} { return Int32(b) },
|
|
},
|
|
{
|
|
name: "String",
|
|
expected: []byte{0x74, 0x65, 0x73, 0x74},
|
|
expectedv: "test",
|
|
actual: PutString("test"),
|
|
unmarshal: func(b []byte) interface{} { return String(b) },
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
if bytes.Compare(tt.actual, tt.expected) != 0 {
|
|
t.Errorf("Put%s failure, expected: %#v, got: %#v", tt.name, tt.expected, tt.actual)
|
|
}
|
|
if actual := tt.unmarshal(tt.actual); !reflect.DeepEqual(actual, tt.expectedv) {
|
|
t.Errorf("%s failure, expected: %#v, got: %#v", tt.name, tt.expectedv, actual)
|
|
}
|
|
}
|
|
}
|