293 lines
11 KiB
Go
293 lines
11 KiB
Go
package tape
|
|
|
|
import "slices"
|
|
import "errors"
|
|
import "testing"
|
|
import "math/rand"
|
|
|
|
const largeNumberNTestRounds = 2048
|
|
const randStringBytes = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
func TestI8(test *testing.T) {
|
|
var buffer [16]byte
|
|
err := EncodeI8[uint8](buffer[:], 5)
|
|
if err.Error() != "encoding int8: wrong buffer length" { test.Fatal(err) }
|
|
err = EncodeI8[uint8](buffer[:0], 5)
|
|
if err.Error() != "encoding int8: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI8[uint8](buffer[:])
|
|
if err.Error() != "decoding int8: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI8[uint8](buffer[:0])
|
|
if err.Error() != "decoding int8: wrong buffer length" { test.Fatal(err) }
|
|
|
|
for number := range uint8(255) {
|
|
err := EncodeI8[uint8](buffer[:1], number)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI8[uint8](buffer[:1])
|
|
if err != nil { test.Fatal(err) }
|
|
if decoded != number {
|
|
test.Fatalf("%d != %d", decoded, number)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI16(test *testing.T) {
|
|
var buffer [16]byte
|
|
err := EncodeI16[uint16](buffer[:], 5)
|
|
if err.Error() != "encoding int16: wrong buffer length" { test.Fatal(err) }
|
|
err = EncodeI16[uint16](buffer[:0], 5)
|
|
if err.Error() != "encoding int16: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI16[uint16](buffer[:])
|
|
if err.Error() != "decoding int16: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI16[uint16](buffer[:0])
|
|
if err.Error() != "decoding int16: wrong buffer length" { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
number := uint16(rand.Int())
|
|
err := EncodeI16[uint16](buffer[:2], number)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI16[uint16](buffer[:2])
|
|
if err != nil { test.Fatal(err) }
|
|
if decoded != number {
|
|
test.Fatalf("%d != %d", decoded, number)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI32(test *testing.T) {
|
|
var buffer [16]byte
|
|
err := EncodeI32[uint32](buffer[:], 5)
|
|
if err.Error() != "encoding int32: wrong buffer length" { test.Fatal(err) }
|
|
err = EncodeI32[uint32](buffer[:0], 5)
|
|
if err.Error() != "encoding int32: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI32[uint32](buffer[:])
|
|
if err.Error() != "decoding int32: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI32[uint32](buffer[:0])
|
|
if err.Error() != "decoding int32: wrong buffer length" { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
number := uint32(rand.Int())
|
|
err := EncodeI32[uint32](buffer[:4], number)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI32[uint32](buffer[:4])
|
|
if err != nil { test.Fatal(err) }
|
|
if decoded != number {
|
|
test.Fatalf("%d != %d", decoded, number)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI64(test *testing.T) {
|
|
var buffer [16]byte
|
|
err := EncodeI64[uint64](buffer[:], 5)
|
|
if err.Error() != "encoding int64: wrong buffer length" { test.Fatal(err) }
|
|
err = EncodeI64[uint64](buffer[:0], 5)
|
|
if err.Error() != "encoding int64: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI64[uint64](buffer[:])
|
|
if err.Error() != "decoding int64: wrong buffer length" { test.Fatal(err) }
|
|
_, err = DecodeI64[uint64](buffer[:0])
|
|
if err.Error() != "decoding int64: wrong buffer length" { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
number := uint64(rand.Int())
|
|
err := EncodeI64[uint64](buffer[:8], number)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI64[uint64](buffer[:8])
|
|
if err != nil { test.Fatal(err) }
|
|
if decoded != number {
|
|
test.Fatalf("%d != %d", decoded, number)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestString(test *testing.T) {
|
|
var buffer [16]byte
|
|
err := EncodeString[string](buffer[:], "hello")
|
|
if !errIs(err, ErrWrongBufferLength, "encoding string: wrong buffer length") { test.Fatal(err) }
|
|
err = EncodeString[string](buffer[:0], "hello")
|
|
if !errIs(err, ErrWrongBufferLength, "encoding string: wrong buffer length") { test.Fatal(err) }
|
|
_, err = DecodeString[string](buffer[:])
|
|
if err != nil { test.Fatal(err) }
|
|
_, err = DecodeString[string](buffer[:0])
|
|
if err != nil { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
length := rand.Intn(16)
|
|
str := randString(length)
|
|
err := EncodeString[string](buffer[:length], str)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeString[string](buffer[:length])
|
|
if err != nil { test.Fatal(err) }
|
|
if decoded != str {
|
|
test.Fatalf("%s != %s", decoded, str)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI8Array(test *testing.T) {
|
|
var buffer [64]byte
|
|
err := EncodeI8Array[uint8](buffer[:], []uint8 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int8: wrong buffer length") { test.Fatal(err) }
|
|
err = EncodeI8Array[uint8](buffer[:0], []uint8 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int8: wrong buffer length") { test.Fatal(err) }
|
|
_, err = DecodeI8Array[uint8](buffer[:])
|
|
if err != nil { test.Fatal(err) }
|
|
_, err = DecodeI8Array[uint8](buffer[:0])
|
|
if err != nil { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
array := randInts[uint8](rand.Intn(16))
|
|
length, _ := I8ArraySize(array)
|
|
if length != len(array) { test.Fatalf("%d != %d", length, len(array)) }
|
|
err := EncodeI8Array[uint8](buffer[:length], array)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI8Array[uint8](buffer[:length])
|
|
if err != nil { test.Fatal(err) }
|
|
if !slices.Equal(decoded, array) {
|
|
test.Fatalf("%v != %v", decoded, array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI16Array(test *testing.T) {
|
|
var buffer [128]byte
|
|
err := EncodeI16Array[uint16](buffer[:], []uint16 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int16: wrong buffer length") { test.Fatal(err) }
|
|
err = EncodeI16Array[uint16](buffer[:0], []uint16 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int16: wrong buffer length") { test.Fatal(err) }
|
|
_, err = DecodeI16Array[uint16](buffer[:])
|
|
if err != nil { test.Fatal(err) }
|
|
_, err = DecodeI16Array[uint16](buffer[:0])
|
|
if err != nil { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
array := randInts[uint16](rand.Intn(16))
|
|
length, _ := I16ArraySize(array)
|
|
if length != 2 * len(array) { test.Fatalf("%d != %d", length, 2 * len(array)) }
|
|
err := EncodeI16Array[uint16](buffer[:length], array)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI16Array[uint16](buffer[:length])
|
|
if err != nil { test.Fatal(err) }
|
|
if !slices.Equal(decoded, array) {
|
|
test.Fatalf("%v != %v", decoded, array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI32Array(test *testing.T) {
|
|
var buffer [256]byte
|
|
err := EncodeI32Array[uint32](buffer[:], []uint32 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int32: wrong buffer length") { test.Fatal(err) }
|
|
err = EncodeI32Array[uint32](buffer[:0], []uint32 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int32: wrong buffer length") { test.Fatal(err) }
|
|
_, err = DecodeI32Array[uint32](buffer[:])
|
|
if err != nil { test.Fatal(err) }
|
|
_, err = DecodeI32Array[uint32](buffer[:0])
|
|
if err != nil { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
array := randInts[uint32](rand.Intn(16))
|
|
length, _ := I32ArraySize(array)
|
|
if length != 4 * len(array) { test.Fatalf("%d != %d", length, 4 * len(array)) }
|
|
err := EncodeI32Array[uint32](buffer[:length], array)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI32Array[uint32](buffer[:length])
|
|
if err != nil { test.Fatal(err) }
|
|
if !slices.Equal(decoded, array) {
|
|
test.Fatalf("%v != %v", decoded, array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestI64Array(test *testing.T) {
|
|
var buffer [512]byte
|
|
err := EncodeI64Array[uint64](buffer[:], []uint64 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int64: wrong buffer length") { test.Fatal(err) }
|
|
err = EncodeI64Array[uint64](buffer[:0], []uint64 { 0, 4, 50, 19 })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []int64: wrong buffer length") { test.Fatal(err) }
|
|
_, err = DecodeI64Array[uint64](buffer[:])
|
|
if err != nil { test.Fatal(err) }
|
|
_, err = DecodeI64Array[uint64](buffer[:0])
|
|
if err != nil { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
array := randInts[uint64](rand.Intn(16))
|
|
length, _ := I64ArraySize(array)
|
|
if length != 8 * len(array) { test.Fatalf("%d != %d", length, 8 * len(array)) }
|
|
err := EncodeI64Array[uint64](buffer[:length], array)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeI64Array[uint64](buffer[:length])
|
|
if err != nil { test.Fatal(err) }
|
|
if !slices.Equal(decoded, array) {
|
|
test.Fatalf("%v != %v", decoded, array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStringArray(test *testing.T) {
|
|
var buffer [8192]byte
|
|
err := EncodeStringArray[string](buffer[:], []string { "0", "4", "50", "19" })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []string: wrong buffer length") { test.Fatal(err) }
|
|
err = EncodeStringArray[string](buffer[:0], []string { "0", "4", "50", "19" })
|
|
if !errIs(err, ErrWrongBufferLength, "encoding []string: wrong buffer length") { test.Fatal(err) }
|
|
_, err = DecodeStringArray[string](buffer[:0])
|
|
if err != nil { test.Fatal(err) }
|
|
|
|
for _ = range largeNumberNTestRounds {
|
|
array := randStrings[string](rand.Intn(16), 16)
|
|
length, _ := StringArraySize(array)
|
|
// TODO test length
|
|
err := EncodeStringArray[string](buffer[:length], array)
|
|
if err != nil { test.Fatal(err) }
|
|
decoded, err := DecodeStringArray[string](buffer[:length])
|
|
if err != nil { test.Fatal(err) }
|
|
if !slices.Equal(decoded, array) {
|
|
test.Fatalf("%v != %v", decoded, array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestU16CastSafe(test *testing.T) {
|
|
number, ok := U16CastSafe(90_000)
|
|
if ok { test.Fatalf("false positive: %v, %v", number, ok) }
|
|
number, ok = U16CastSafe(-478)
|
|
if ok { test.Fatalf("false positive: %v, %v", number, ok) }
|
|
number, ok = U16CastSafe(3870)
|
|
if !ok { test.Fatalf("false negative: %v, %v", number, ok) }
|
|
if got, correct := number, uint16(3870); got != correct {
|
|
test.Fatalf("not equal: %v %v", got, correct)
|
|
}
|
|
number, ok = U16CastSafe(0)
|
|
if !ok { test.Fatalf("false negative: %v, %v", number, ok) }
|
|
if got, correct := number, uint16(0); got != correct {
|
|
test.Fatalf("not equal: %v %v", got, correct)
|
|
}
|
|
}
|
|
|
|
func randString(length int) string {
|
|
buffer := make([]byte, length)
|
|
for index := range buffer {
|
|
buffer[index] = randStringBytes[rand.Intn(len(randStringBytes))]
|
|
}
|
|
return string(buffer)
|
|
}
|
|
|
|
func randInts[T interface { ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 }] (length int) []T {
|
|
buffer := make([]T, length)
|
|
for index := range buffer {
|
|
buffer[index] = T(rand.Int())
|
|
}
|
|
return buffer
|
|
}
|
|
|
|
func randStrings[T interface { ~string }] (length, maxItemLength int) []T {
|
|
buffer := make([]T, length)
|
|
for index := range buffer {
|
|
buffer[index] = T(randString(rand.Intn(maxItemLength)))
|
|
}
|
|
return buffer
|
|
}
|
|
|
|
func errIs(err error, wraps error, description string) bool {
|
|
return err != nil && (wraps == nil || errors.Is(err, wraps)) && err.Error() == description
|
|
}
|