151 lines
3.1 KiB
Go
151 lines
3.1 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package cstruct
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"testing"
|
|
)
|
|
|
|
func TestPadBytes(t *testing.T) {
|
|
testCases := []struct {
|
|
offset int
|
|
size int
|
|
want int
|
|
}{
|
|
// No padding at beginning of structure
|
|
{0, 1, 0},
|
|
{0, 2, 0},
|
|
{0, 4, 0},
|
|
{0, 8, 0},
|
|
|
|
// No padding for single bytes
|
|
{1, 1, 0},
|
|
|
|
// Single byte padding
|
|
{1, 2, 1},
|
|
{3, 4, 1},
|
|
|
|
// Multi-byte padding
|
|
{1, 4, 3},
|
|
{2, 8, 6},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run(fmt.Sprintf("%d_%d_%d", tc.offset, tc.size, tc.want), func(t *testing.T) {
|
|
got := padBytes(tc.offset, tc.size)
|
|
if got != tc.want {
|
|
t.Errorf("got=%d; want=%d", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecoder(t *testing.T) {
|
|
t.Run("UnsignedTypes", func(t *testing.T) {
|
|
dec := func(n int) *Decoder {
|
|
buf := make([]byte, n)
|
|
buf[0] = 1
|
|
|
|
d := NewDecoder(buf)
|
|
|
|
// Use t.Cleanup to perform an assertion on this
|
|
// decoder after the test code is finished with it.
|
|
t.Cleanup(func() {
|
|
if err := d.Err(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
return d
|
|
}
|
|
if got := dec(2).Uint16(); got != 1 {
|
|
t.Errorf("uint16: got=%d; want=1", got)
|
|
}
|
|
if got := dec(4).Uint32(); got != 1 {
|
|
t.Errorf("uint32: got=%d; want=1", got)
|
|
}
|
|
if got := dec(8).Uint64(); got != 1 {
|
|
t.Errorf("uint64: got=%d; want=1", got)
|
|
}
|
|
if got := dec(pointerSize / 8).Uintptr(); got != 1 {
|
|
t.Errorf("uintptr: got=%d; want=1", got)
|
|
}
|
|
})
|
|
|
|
t.Run("SignedTypes", func(t *testing.T) {
|
|
dec := func(n int) *Decoder {
|
|
// Make a buffer of the exact size that consists of 0xff bytes
|
|
buf := make([]byte, n)
|
|
for i := range n {
|
|
buf[i] = 0xff
|
|
}
|
|
|
|
d := NewDecoder(buf)
|
|
|
|
// Use t.Cleanup to perform an assertion on this
|
|
// decoder after the test code is finished with it.
|
|
t.Cleanup(func() {
|
|
if err := d.Err(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
return d
|
|
}
|
|
if got := dec(2).Int16(); got != -1 {
|
|
t.Errorf("int16: got=%d; want=-1", got)
|
|
}
|
|
if got := dec(4).Int32(); got != -1 {
|
|
t.Errorf("int32: got=%d; want=-1", got)
|
|
}
|
|
if got := dec(8).Int64(); got != -1 {
|
|
t.Errorf("int64: got=%d; want=-1", got)
|
|
}
|
|
})
|
|
|
|
t.Run("InsufficientData", func(t *testing.T) {
|
|
dec := func(n int) *Decoder {
|
|
// Make a buffer that's too small and contains arbitrary bytes
|
|
buf := make([]byte, n-1)
|
|
for i := range n - 1 {
|
|
buf[i] = 0xAD
|
|
}
|
|
|
|
// Use t.Cleanup to perform an assertion on this
|
|
// decoder after the test code is finished with it.
|
|
d := NewDecoder(buf)
|
|
t.Cleanup(func() {
|
|
if err := d.Err(); err == nil || !errors.Is(err, io.EOF) {
|
|
t.Errorf("(n=%d) expected io.EOF; got=%v", n, err)
|
|
}
|
|
})
|
|
return d
|
|
}
|
|
|
|
dec(2).Uint16()
|
|
dec(4).Uint32()
|
|
dec(8).Uint64()
|
|
dec(pointerSize / 8).Uintptr()
|
|
|
|
dec(2).Int16()
|
|
dec(4).Int32()
|
|
dec(8).Int64()
|
|
})
|
|
|
|
t.Run("Bytes", func(t *testing.T) {
|
|
d := NewDecoder([]byte("hello worldasdf"))
|
|
t.Cleanup(func() {
|
|
if err := d.Err(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
|
|
buf := make([]byte, 11)
|
|
d.Bytes(buf)
|
|
if got := string(buf); got != "hello world" {
|
|
t.Errorf("bytes: got=%q; want=%q", got, "hello world")
|
|
}
|
|
})
|
|
}
|