| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- // Copyright (c) Tailscale Inc & contributors
- // 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")
- }
- })
- }
|