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 }