route/vendor/github.com/bifurcation/mint/syntax/encode_test.go

270 lines
6.0 KiB
Go

package syntax
import (
"bytes"
"encoding/hex"
"fmt"
"strings"
"testing"
)
type CrypticString string
var (
crypticStringMarshalCalls = 0
crypticStringUnmarshalCalls = 0
)
// A CrypticString marshalls as one length octet followed by the
// UTF-8 bytes of the string, XOR'ed with an increasing sequence
// starting with the length plus one (L+1, L+2, ...).
func (cs CrypticString) MarshalTLS() ([]byte, error) {
crypticStringMarshalCalls += 1
l := byte(len(cs))
b := []byte(cs)
for i := range b {
b[i] ^= l + byte(i) + 1
}
return append([]byte{l}, b...), nil
}
func (cs *CrypticString) UnmarshalTLS(data []byte) (int, error) {
crypticStringUnmarshalCalls += 1
if len(data) == 0 {
return 0, fmt.Errorf("Length of CrypticString must be at least 1")
}
l := data[0]
if len(data) < int(l)+1 {
return 0, fmt.Errorf("TLS data not long enough for CrypticString")
}
b := data[1 : l+1]
for i := range b {
b[i] ^= l + byte(i) + 1
}
*cs = CrypticString(string(b))
return int(l + 1), nil
}
// Test cases to use for encode and decode
var (
x8 uint8 = 0xA0
z8 = []byte{0xA0}
x16 uint16 = 0xB0A0
z16, _ = hex.DecodeString("B0A0")
x32 uint32 = 0xD0C0B0A0
z32, _ = hex.DecodeString("D0C0B0A0")
x64 uint64 = 0xD0C0B0A090807060
z64, _ = hex.DecodeString("D0C0B0A090807060")
xvi = struct {
U8 uint8 `tls:"varint"`
U16 uint16 `tls:"varint"`
U32 uint32 `tls:"varint"`
U64 uint64 `tls:"varint"`
}{
U8: 0x3f,
U16: 0x3fff,
U32: 0x3fffffff,
U64: 0x3fffffffffffffff,
}
zvi, _ = hex.DecodeString("3f" + "7fff" + "bfffffff" + "ffffffffffffffff")
xa = [5]uint16{0x1111, 0x2222, 0x3333, 0x4444, 0x5555}
za, _ = hex.DecodeString("11112222333344445555")
xv20 = struct {
V []byte `tls:"head=1"`
}{V: bytes.Repeat([]byte{0xA0}, 0x20)}
zv20, _ = hex.DecodeString("20" + strings.Repeat("A0", 0x20))
xv200 = struct {
V []byte `tls:"head=2"`
}{V: bytes.Repeat([]byte{0xA0}, 0x200)}
zv200, _ = hex.DecodeString("0200" + strings.Repeat("A0", 0x200))
xv20000 = struct {
V []byte `tls:"head=3"`
}{V: bytes.Repeat([]byte{0xA0}, 0x20000)}
zv20000, _ = hex.DecodeString("020000" + strings.Repeat("A0", 0x20000))
xvENohead = struct {
V []byte
}{V: xv20.V}
xvEhead = struct {
V []byte `tls:"head=1"`
}{V: bytes.Repeat([]byte{0xA0}, 0x100)}
xvEmax = struct {
V []byte `tls:"head=1,max=31"`
}{V: xv20.V}
xvEmin = struct {
V []byte `tls:"head=1,min=33"`
}{V: xv20.V}
xs1 = struct {
A uint16
B []uint8 `tls:"head=2"`
C [4]uint32
}{
A: 0xB0A0,
B: []uint8{0xA0, 0xA1, 0xA2, 0xA3, 0xA4},
C: [4]uint32{0x10111213, 0x20212223, 0x30313233, 0x40414243},
}
zs1, _ = hex.DecodeString("B0A0" + "0005A0A1A2A3A4" + "10111213202122233031323340414243")
xm = CrypticString("hello")
zm, _ = hex.DecodeString("056e62646565")
xsm = struct {
A CrypticString
B uint16
C CrypticString
}{
A: CrypticString("hello"),
B: x16,
C: CrypticString("... world!"),
}
zsm, _ = hex.DecodeString("056e62646565" + "B0A0" + "0a2522232e787f637e7735")
xsp = struct {
A uint16
B *CrypticString
}{
A: x16,
B: &xm,
}
zsp, _ = hex.DecodeString("B0A0" + "056e62646565")
)
func TestEncodeInvalidCases(t *testing.T) {
x := struct {
Strings []string
}{Strings: []string{"asdf"}}
_, err := Marshal(x)
if err == nil {
t.Fatalf("Agreed to marshal an unsupported type")
}
}
func TestEncodeBasicTypes(t *testing.T) {
y8, err := Marshal(x8)
if err != nil || !bytes.Equal(y8, z8) {
t.Fatalf("uint8 encode failed [%v] [%x]", err, y8)
}
y16, err := Marshal(x16)
if err != nil || !bytes.Equal(y16, z16) {
t.Fatalf("uint16 encode failed [%v] [%x]", err, y16)
}
y32, err := Marshal(x32)
if err != nil || !bytes.Equal(y32, z32) {
t.Fatalf("uint32 encode failed [%v] [%x]", err, y32)
}
y64, err := Marshal(x64)
if err != nil || !bytes.Equal(y64, z64) {
t.Fatalf("uint64 encode failed [%v] [%x]", err, y64)
}
}
func TestEncodeVarint(t *testing.T) {
yvi, err := Marshal(xvi)
if err != nil || !bytes.Equal(yvi, zvi) {
t.Fatalf("varint encode failed [%v] [%x]", err, yvi)
}
}
func TestEncodeArray(t *testing.T) {
ya, err := Marshal(xa)
if err != nil || !bytes.Equal(ya, za) {
t.Fatalf("[5]uint8 encode failed [%v] [%x]", err, ya)
}
}
func TestEncodeSlice(t *testing.T) {
yv20, err := Marshal(xv20)
if err != nil || !bytes.Equal(yv20, zv20) {
t.Fatalf("[0x20]uint8 encode failed [%v] [%x]", err, yv20)
}
yv200, err := Marshal(xv200)
if err != nil || !bytes.Equal(yv200, zv200) {
t.Fatalf("[0x200]uint8 encode failed [%v] [%x]", err, yv200)
}
yv20000, err := Marshal(xv20000)
if err != nil || !bytes.Equal(yv20000, zv20000) {
t.Fatalf("[0x20000]uint8 encode failed [%v] [%x]", err, yv20000)
}
yE, err := Marshal(xvENohead)
if err == nil {
t.Fatalf("Allowed marshal with no header size [%x]", yE)
}
yE, err = Marshal(xvEhead)
if err == nil {
t.Fatalf("Allowed marshal exceeding header size [%x]", yE)
}
yE, err = Marshal(xvEmax)
if err == nil {
t.Fatalf("Allowed marshal exceeding max [%x]", yE)
}
yE, err = Marshal(xvEmin)
if err == nil {
t.Fatalf("Allowed marshal below min [%x]", yE)
}
}
func TestEncodeStruct(t *testing.T) {
ys1, err := Marshal(xs1)
if err != nil || !bytes.Equal(ys1, zs1) {
t.Fatalf("struct encode failed [%v] [%x]", err, ys1)
}
}
func TestEncodeMarshaler(t *testing.T) {
crypticStringMarshalCalls = 0
ym, err := Marshal(xm)
if err != nil || !bytes.Equal(ym, zm) {
t.Fatalf("Marshaler encode failed [%v] [%x]", err, ym)
}
if crypticStringMarshalCalls != 1 {
t.Fatalf("MarshalTLS() was not called exactly once [%v]", crypticStringMarshalCalls)
}
crypticStringMarshalCalls = 0
ysm, err := Marshal(xsm)
if err != nil || !bytes.Equal(ysm, zsm) {
t.Fatalf("Struct-embedded marshaler encode failed [%v] [%x]", err, ysm)
}
if crypticStringMarshalCalls != 2 {
t.Fatalf("MarshalTLS() was not called exactly twice [%v]", crypticStringMarshalCalls)
}
}
func TestEncodeStructWithPointer(t *testing.T) {
ysp, err := Marshal(xsp)
if err != nil || !bytes.Equal(ysp, zsp) {
t.Fatalf("struct encode failed [%v] [%x]", err, ysp)
}
}