ErrBadUTF8 = errors.New("invalid UTF-8")
ErrBadInt = errors.New("bad int value")
ErrBadMagic = errors.New("bad magic value")
- ErrTaiReserved = errors.New("reserved TAI64 values in use")
- ErrTaiNonMinimal = errors.New("non-minimal TAI64")
+ ErrTAIReserved = errors.New("reserved TAI64 values in use")
+ ErrTAINonMinimal = errors.New("non-minimal TAI64")
ErrTooManyNsecs = errors.New("too many nanoseconds")
ErrTooManyAsecs = errors.New("too many attoseconds")
)
return
}
if be.Get([]byte(s)[:8]) > (1 << 63) {
- err = ErrTaiReserved
+ err = ErrTAIReserved
return
}
if l > 8 {
nsecs := be.Get([]byte(s)[8 : 8+4])
if l == 12 && nsecs == 0 {
- err = ErrTaiNonMinimal
+ err = ErrTAINonMinimal
return
}
if nsecs > 999999999 {
if l > 12 {
asecs := be.Get([]byte(s)[8+4 : 8+4+4])
if asecs == 0 {
- err = ErrTaiNonMinimal
+ err = ErrTAINonMinimal
return
}
if asecs > 999999999 {
// Write an encoded BLOB atom.
func BlobEncode(w io.Writer, chunkLen int64, r io.Reader) (written int64, err error) {
+ if chunkLen == 0 {
+ return 0, errors.New("zero chunkLen specified")
+ }
{
l := make([]byte, 9)
l[0] = byte(AtomBLOB)
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "encoding/hex"
"io"
- "reflect"
"strings"
"testing"
"testing/quick"
+
+ "go.cypherpunks.su/keks/be"
)
-func TestBinaryEmpty(t *testing.T) {
- object := []byte{}
- binstring := mustHexDec("80")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinEmpty(t *testing.T) {
+ obj := []byte{}
+ bin := mustHexDec("80")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.([]byte)
+ casted, ok := decoded.([]byte)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, obj) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(udecoded, object) {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestBinary1234(t *testing.T) {
- object := []byte{0x01, 0x02, 0x03, 0x04}
- binstring := mustHexDec("8401020304")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBin1234(t *testing.T) {
+ obj := []byte{0x01, 0x02, 0x03, 0x04}
+ bin := mustHexDec("8401020304")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.([]byte)
+ casted, ok := decoded.([]byte)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, obj) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(udecoded, object) {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(udecoded), udecoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestBinaryLen62(t *testing.T) {
- object := bytes.Repeat([]byte{'a'}, 62)
- binstring := mustHexDec("BD01" + strings.Repeat("61", 62))
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinLen62(t *testing.T) {
+ obj := bytes.Repeat([]byte{'a'}, 62)
+ bin := mustHexDec("BD01" + strings.Repeat("61", 62))
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.([]byte)
+ casted, ok := decoded.([]byte)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if !bytes.Equal(udecoded, object) {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(udecoded), udecoded)
- t.FailNow()
+ if !bytes.Equal(casted, obj) {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestBinaryLen318(t *testing.T) {
- object := bytes.Repeat([]byte{'a'}, 318)
- binstring := mustHexDec("BE0001" + strings.Repeat("61", 318))
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinLen318(t *testing.T) {
+ obj := bytes.Repeat([]byte{'a'}, 62+255+1)
+ bin := mustHexDec("BE0001" + strings.Repeat("61", 62+255+1))
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.([]byte)
+ casted, ok := decoded.([]byte)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, obj) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(udecoded, object) {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(udecoded), udecoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestBinaryLen65853(t *testing.T) {
- object := bytes.Repeat([]byte{'a'}, 65853)
- binstring := mustHexDec("BF0000000000000000" + strings.Repeat("61", 65853))
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinLen65853(t *testing.T) {
+ obj := bytes.Repeat([]byte{'a'}, 62+255+65535+1)
+ bin := mustHexDec("BF0000000000000000" + strings.Repeat("61", 62+255+65535+1))
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.([]byte)
+ casted, ok := decoded.([]byte)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, obj) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(udecoded, object) {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(udecoded), udecoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestBinaryThrowsWhenNotEnoughData(t *testing.T) {
- binstring := mustHexDec("84010203")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinNotEnoughData(t *testing.T) {
+ bin := mustHexDec("84010203")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
+ t.Fatal()
}
}
-func TestBinaryThrowsWhenNotEnoughDataForLength8(t *testing.T) {
- binstring := mustHexDec("BD01" + strings.Repeat("61", 61))
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinNotEnoughDataForLength8(t *testing.T) {
+ bin := mustHexDec("BD01" + strings.Repeat("61", 61))
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
+ t.Fatal()
}
}
-func TestBinaryThrowsWhenNotEnoughDataForLength16(t *testing.T) {
- binstring := mustHexDec("BE0001" + strings.Repeat("61", 317))
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinNotEnoughDataForLength16(t *testing.T) {
+ bin := mustHexDec("BE0001" + strings.Repeat("61", 317))
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
+ t.Fatal()
}
}
-func TestBinaryThrowsWhenNotEnoughDataForLength64(t *testing.T) {
- binstring := mustHexDec("BF0000000000000000" + strings.Repeat("61", 65852))
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBinNotEnoughDataForLength64(t *testing.T) {
+ bin := mustHexDec("BF0000000000000000" + strings.Repeat("61", 65852))
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
+ t.Fatal()
+ }
+}
+
+func TestBinTooLong(t *testing.T) {
+ bin := make([]byte, 9)
+ bin[0] = 0xBF
+ for _, l := range []uint64{
+ 1 << 63,
+ (1 << 63) - 63,
+ (1 << 63) - 63 - ((1 << 8) - 1),
+ (1 << 63) - 63 - ((1 << 8) - 1) - ((1 << 16) - 1) + 1,
+ } {
+ be.Put(bin[1:], l)
+ decoder := NewDecoderFromBytes(bin, nil)
+ _, err := decoder.Decode()
+ if err != ErrLenTooBig {
+ t.Fatal(err)
+ }
}
}
-func TestBinarySymmetric(t *testing.T) {
- f := func(object []byte) bool {
- encoded, err := EncodeBuf(object, nil)
+func TestBinNotTooLong(t *testing.T) {
+ bin := make([]byte, 9)
+ bin[0] = 0xBF
+ be.Put(bin[1:], (1<<63)-63-((1<<8)-1)-((1<<16)-1))
+ decoder := NewDecoderFromReader(bytes.NewReader(bin), nil)
+ defer func() { recover() }()
+ _, err := decoder.Decode()
+ // it won't reach that code because it can not allocate so much
+ // memory in .getBytes(), but that means, that no error was returned
+ t.Fatal(err)
+}
+
+func TestBinMaxStrLen(t *testing.T) {
+ f := func(bin []byte) bool {
+ if len(bin) == 0 {
+ return true
+ }
+ encoded, err := EncodeBuf(bin, nil)
+ if err != nil {
+ panic(err)
+ }
+ decoder := NewDecoderFromBytes(encoded,
+ &DecodeOpts{MaxStrLen: int64(len(bin) + 1)})
+ _, err = decoder.Decode()
if err != nil {
return false
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder = NewDecoderFromBytes(encoded,
+ &DecodeOpts{MaxStrLen: int64(len(bin))})
+ _, err = decoder.Decode()
if err != nil {
return false
}
- udecoded, ok := decoded.([]byte)
- if !ok {
- t.Fatalf("failed to cast")
+ if len(bin) == 1 {
+ return true
}
- if !bytes.Equal(object, udecoded) {
- t.Logf("Expected <%s, %d>", reflect.TypeOf(object), object)
- t.Logf("Instead <%s, %d>", reflect.TypeOf(udecoded), udecoded)
+ decoder = NewDecoderFromBytes(encoded,
+ &DecodeOpts{MaxStrLen: int64(len(bin) - 1)})
+ _, err = decoder.Decode()
+ return err != nil
+ }
+ if err := quick.Check(f, nil); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestBinSymmetric(t *testing.T) {
+ f := func(bin []byte) bool {
+ encoded, err := EncodeBuf(bin, nil)
+ if err != nil {
+ panic(err)
+ }
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ return false
+ }
+ casted, ok := decoded.([]byte)
+ if !ok {
return false
}
- return true
+ return bytes.Equal(bin, casted)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "encoding/hex"
"io"
- "reflect"
"testing"
"testing/quick"
+
+ "go.cypherpunks.su/keks/be"
)
func TestBlobMultipleOfChunkLen(t *testing.T) {
- object := BlobChunked{
- Chunks: []string{"test", "data"},
+ bin := bytes.Join([][]byte{
+ mustHexDec("0B0000000000000003"),
+ {0x84},
+ []byte("test"),
+ {0x84},
+ []byte("data"),
+ {0x80},
+ }, nil)
+ data := []byte("test" + "data")
+ encoded, err := EncodeBuf(BlobReader{
ChunkLen: 4,
- }
- binstring := mustHexDec("0B00000000000000038474657374846461746180")
- encoded, err := EncodeBuf(object, nil)
+ R: bytes.NewReader(data),
+ }, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(BlobChunked)
+ casted, ok := decoded.(BlobChunked)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if object.ChunkLen != udecoded.ChunkLen {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
+ if casted.Len() != 2*4 {
+ t.Fatal("Len() differs")
}
- for i := range len(object.Chunks) {
- if object.Chunks[i] != udecoded.Chunks[i] {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
- }
+ if casted.ChunkLen != 4 {
+ t.Fatal("ChunkLen differs")
+ }
+ if len(casted.Chunks) != 2 {
+ t.Fatal("len(Chunks) differs")
+ }
+ if casted.Chunks[0] != "test" {
+ t.Fatal("Chunks[0] differs")
+ }
+ if casted.Chunks[1] != "data" {
+ t.Fatal("Chunks[1] differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+ got, err := io.ReadAll(casted.Reader())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(got, data) {
+ t.Fatal("reader differs")
}
}
func TestBlobLargerOfChunkLen(t *testing.T) {
- object := BlobChunked{
- Chunks: []string{"test", "data", "2"},
+ bin := bytes.Join([][]byte{
+ mustHexDec("0B0000000000000003"),
+ {0x84},
+ []byte("test"),
+ {0x84},
+ []byte("data"),
+ {0x81},
+ []byte("2"),
+ }, nil)
+ data := []byte("test" + "data" + "2")
+ encoded, err := EncodeBuf(BlobReader{
ChunkLen: 4,
- }
- binstring := mustHexDec("0B0000000000000003847465737484646174618132")
- encoded, err := EncodeBuf(object, nil)
+ R: bytes.NewReader(data),
+ }, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(BlobChunked)
+ casted, ok := decoded.(BlobChunked)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if object.ChunkLen != udecoded.ChunkLen {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
+ if casted.Len() != 2*4+1 {
+ t.Fatal("Len() differs")
}
- for i := range len(object.Chunks) {
- if object.Chunks[i] != udecoded.Chunks[i] {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
- }
+ if casted.ChunkLen != 4 {
+ t.Fatal("ChunkLen differs")
+ }
+ if len(casted.Chunks) != 3 {
+ t.Fatal("len(Chunks) differs")
+ }
+ if casted.Chunks[0] != "test" {
+ t.Fatal("Chunks[0] differs")
+ }
+ if casted.Chunks[1] != "data" {
+ t.Fatal("Chunks[1] differs")
+ }
+ if casted.Chunks[2] != "2" {
+ t.Fatal("Chunks[2] differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+ got, err := io.ReadAll(casted.Reader())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(got, data) {
+ t.Fatal("reader differs")
}
}
func TestBlobEmpty(t *testing.T) {
- object := BlobChunked{
- Chunks: []string{},
+ bin := mustHexDec("0B0000000000000003" + "80")
+ encoded, err := EncodeBuf(BlobReader{
ChunkLen: 4,
- }
- binstring := mustHexDec("0B000000000000000380")
- encoded, err := EncodeBuf(object, nil)
+ R: bytes.NewReader(nil),
+ }, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(BlobChunked)
+ casted, ok := decoded.(BlobChunked)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if object.ChunkLen != udecoded.ChunkLen {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
+ if casted.Len() != 0 {
+ t.Fatal("Len() differs")
}
- for i := range len(object.Chunks) {
- if object.Chunks[i] != udecoded.Chunks[i] {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
- }
+ if casted.ChunkLen != 4 {
+ t.Fatal("ChunkLen differs")
+ }
+ if len(casted.Chunks) != 0 {
+ t.Fatal("len(Chunks) differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+ got, err := io.ReadAll(casted.Reader())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(got, []byte{}) {
+ t.Fatal("reader differs")
}
}
func TestBlobSymmetric(t *testing.T) {
- f := func(data []byte, ChunkLen uint8) bool {
- object := BlobReader{ChunkLen: int64(ChunkLen), R: bytes.NewReader(data)}
- encoded, err := EncodeBuf(object, nil)
+ var err error
+ f := func(chunkLen, chunksN uint8) bool {
+ if chunkLen == 0 {
+ chunkLen++
+ }
+ chunks := make([][]byte, 0, chunksN)
+ mr := make([]io.Reader, 0, chunksN)
+ for range chunksN {
+ chunk := make([]byte, chunkLen)
+ if _, err = io.ReadFull(PRNG, chunk); err != nil {
+ panic(err)
+ }
+ chunks = append(chunks, chunk)
+ mr = append(mr, bytes.NewReader(chunk))
+ }
+ encoded, err := EncodeBuf(BlobReader{
+ ChunkLen: int64(chunkLen),
+ R: io.MultiReader(mr...),
+ }, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
- return false
+ t.Fatal(err)
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- udecoded, ok := decoded.(BlobChunked)
+ casted, ok := decoded.(BlobChunked)
if !ok {
- t.Fatalf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if object.ChunkLen != udecoded.ChunkLen {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
- return false
+ if casted.Len() != int64(chunkLen)*int64(chunksN) {
+ t.Fatal("Len() differs")
}
- for i := range len(data) {
- if data[i] != udecoded.Chunks[i/int(ChunkLen)][i%int(ChunkLen)] {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
- return false
- }
+ if casted.ChunkLen != int64(chunkLen) {
+ t.Fatal("ChunkLen differs")
}
- for i := range int(ChunkLen)*(len(data)/int(ChunkLen)) - len(data) {
- if udecoded.Chunks[len(data)/int(ChunkLen)][i] != 0 {
- t.Fatalf("expected <%s, %v>", reflect.TypeOf(object), object)
- t.Fatalf("instead <%s, %v>", reflect.TypeOf(decoded), decoded)
- return false
+ if len(casted.Chunks) != int(chunksN) {
+ t.Fatal("len(Chunks) differs")
+ }
+ for i := range len(chunks) {
+ if casted.Chunks[i] != string(chunks[i]) {
+ t.Fatal("chunk differs")
}
}
return true
}
}
-func TestBlobThrowsWhenNotEnoughData(t *testing.T) {
- binstring := mustHexDec("0B00000000000000038474657374846461")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBlobNotEnoughData(t *testing.T) {
+ bin := bytes.Join([][]byte{
+ mustHexDec("0B0000000000000003"),
+ {0x84},
+ []byte("test"),
+ {0x84},
+ []byte("da"),
+ }, nil)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
+ }
+}
+
+func TestBlobTooLong(t *testing.T) {
+ bin := make([]byte, 1+8)
+ bin[0] = byte(AtomBLOB)
+ be.Put(bin[1:], (1<<63)-1)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrLenTooBig {
+ t.Fatal(err)
}
}
-func TestBlobThrowsWhenNotEnoughDataForLength(t *testing.T) {
- binstring := mustHexDec("0B00000000")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBlobNotEnoughDataForLength(t *testing.T) {
+ bin := mustHexDec("0B00000000")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
}
}
-func TestBlobThrowsWhenWrongTerminatorLength(t *testing.T) {
- binstring := mustHexDec("0B0000000000000003847465737484646174618A7465726D696E61746F72")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBlobWrongTerminatorLength(t *testing.T) {
+ bin := bytes.Join([][]byte{
+ mustHexDec("0B0000000000000003"),
+ {0x84},
+ []byte("test"),
+ {0x84},
+ []byte("data"),
+ {0x8A},
+ []byte("terminator"),
+ }, nil)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != ErrBlobBadChunkLen {
- t.Fatalf("expected ErrBlobBadChunkLen, got %s", err)
+ t.Fatal(err)
}
}
-func TestBlobThrowsWhenWrongTerminatorTag(t *testing.T) {
- binstring := mustHexDec("0B00000000000000038474657374846461746104746861742077617320612077726F6E6720746167")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBlobWrongTerminatorTag(t *testing.T) {
+ bin := bytes.Join([][]byte{
+ mustHexDec("0B0000000000000003"),
+ {0x84},
+ []byte("test"),
+ {0x84},
+ []byte("data"),
+ {0x04},
+ []byte("that was a wrong tag"),
+ }, nil)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != ErrBlobBadAtom {
- t.Fatalf("expected ErrBlobBadChunkLen, got %s", err)
+ t.Fatal(err)
}
}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "encoding/hex"
- "reflect"
"testing"
)
-func TestTrue(t *testing.T) {
- object := true
- binstring := mustHexDec("03")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBoolTrue(t *testing.T) {
+ bin := mustHexDec("03")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(true, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if decoded != object {
- t.Logf("expected type %s, value true", reflect.TypeOf(object))
- t.Logf("got type %s, value %t", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ casted, ok := decoded.(bool)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !casted {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestFalse(t *testing.T) {
- object := false
- binstring := mustHexDec("02")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestBoolFalse(t *testing.T) {
+ bin := mustHexDec("02")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(false, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(bool)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if casted {
+ t.Fatal("casted differs")
}
- if decoded != object {
- t.Logf("expected type %s, value false", reflect.TypeOf(object))
- t.Logf("got type %s, value %+v", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
"io"
- "reflect"
"testing"
)
-func TestThrowsWhenEncodingFloat(t *testing.T) {
+func TestEncodingFloat(t *testing.T) {
_, err := EncodeBuf(1.5, nil)
if err == nil {
- t.Fatalf("expected Error, got nil")
+ t.Fatal(err)
}
}
func TestFloat16Loads(t *testing.T) {
- decoded, err := NewDecoderFromBytes(append([]byte{0x10}, bytes.Repeat([]byte{0x11}, 2)...), nil).Decode()
- object := Raw(append([]byte{0x10}, bytes.Repeat([]byte{0x11}, 2)...))
+ bin := append([]byte{0x10}, bytes.Repeat([]byte{0x11}, 2)...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %v", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(Raw)
+ casted, ok := decoded.(Raw)
if !ok {
- t.Fatalf("expected Raw, got %v", reflect.TypeOf(decoded))
+ t.Fatal("failed to cast")
}
- if !bytes.Equal(object, udecoded) {
- t.Fatalf("expected %v, got %v", object, decoded)
+ if !bytes.Equal(casted, bin) {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
func TestFloat32Loads(t *testing.T) {
- decoded, err := NewDecoderFromBytes(append([]byte{0x11}, bytes.Repeat([]byte{0x11}, 4)...), nil).Decode()
- object := Raw(append([]byte{0x11}, bytes.Repeat([]byte{0x11}, 4)...))
+ bin := append([]byte{0x11}, bytes.Repeat([]byte{0x11}, 4)...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %v", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(Raw)
+ casted, ok := decoded.(Raw)
if !ok {
- t.Fatalf("expected Raw, got %v", reflect.TypeOf(decoded))
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, bin) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(object, udecoded) {
- t.Fatalf("expected %v, got %v", object, decoded)
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
func TestFloat64Loads(t *testing.T) {
- decoded, err := NewDecoderFromBytes(append([]byte{0x12}, bytes.Repeat([]byte{0x11}, 8)...), nil).Decode()
- object := Raw(append([]byte{0x12}, bytes.Repeat([]byte{0x11}, 8)...))
+ bin := append([]byte{0x12}, bytes.Repeat([]byte{0x12}, 8)...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %v", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(Raw)
+ casted, ok := decoded.(Raw)
if !ok {
- t.Fatalf("expected Raw, got %v", reflect.TypeOf(decoded))
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, bin) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(object, udecoded) {
- t.Fatalf("expected %v, got %v", object, decoded)
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
func TestFloat128Loads(t *testing.T) {
- decoded, err := NewDecoderFromBytes(append([]byte{0x13}, bytes.Repeat([]byte{0x11}, 16)...), nil).Decode()
- object := Raw(append([]byte{0x13}, bytes.Repeat([]byte{0x11}, 16)...))
+ bin := append([]byte{0x13}, bytes.Repeat([]byte{0x13}, 16)...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %v", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(Raw)
+ casted, ok := decoded.(Raw)
if !ok {
- t.Fatalf("expected Raw, got %v", reflect.TypeOf(decoded))
+ t.Fatal("failed to cast")
}
- if !bytes.Equal(object, udecoded) {
- t.Fatalf("expected %v, got %v", object, decoded)
+ if !bytes.Equal(casted, bin) {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
func TestFloat256Loads(t *testing.T) {
- decoded, err := NewDecoderFromBytes(append([]byte{0x14}, bytes.Repeat([]byte{0x11}, 32)...), nil).Decode()
- object := Raw(append([]byte{0x14}, bytes.Repeat([]byte{0x11}, 32)...))
+ bin := append([]byte{0x14}, bytes.Repeat([]byte{0x14}, 32)...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %v", err)
+ t.Fatal(err)
}
- udecoded, ok := decoded.(Raw)
+ casted, ok := decoded.(Raw)
if !ok {
- t.Fatalf("expected Raw, got %v", reflect.TypeOf(decoded))
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted, bin) {
+ t.Fatal("casted differs")
}
- if !bytes.Equal(object, udecoded) {
- t.Fatalf("expected %v, got %v", object, decoded)
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestFloatThrowhsWhenNotEnoughDataForFloat256(t *testing.T) {
- _, err := NewDecoderFromBytes(append([]byte{0x14}, bytes.Repeat([]byte{0x11}, 32-1)...), nil).Decode()
+func TestFloat16NotEnoughData(t *testing.T) {
+ bin := append([]byte{0x10}, bytes.Repeat([]byte{0x11}, 2-1)...)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
}
}
-func TestFloatThrowhsWhenNotEnoughDataForFloat128(t *testing.T) {
- _, err := NewDecoderFromBytes(append([]byte{0x13}, bytes.Repeat([]byte{0x11}, 16-1)...), nil).Decode()
+func TestFloat32NotEnoughData(t *testing.T) {
+ bin := append([]byte{0x11}, bytes.Repeat([]byte{0x11}, 4-1)...)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
}
}
-func TestFloatThrowhsWhenNotEnoughDataForFloat64(t *testing.T) {
- _, err := NewDecoderFromBytes(append([]byte{0x12}, bytes.Repeat([]byte{0x11}, 8-1)...), nil).Decode()
+func TestFloat64NotEnoughData(t *testing.T) {
+ bin := append([]byte{0x12}, bytes.Repeat([]byte{0x11}, 8-1)...)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
}
}
-func TestFloatThrowhsWhenNotEnoughDataForFloat32(t *testing.T) {
- _, err := NewDecoderFromBytes(append([]byte{0x11}, bytes.Repeat([]byte{0x11}, 4-1)...), nil).Decode()
+func TestFloat128NotEnoughData(t *testing.T) {
+ bin := append([]byte{0x13}, bytes.Repeat([]byte{0x11}, 16-1)...)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
}
}
-func TestFloatThrowhsWhenNotEnoughDataForFloat16(t *testing.T) {
- _, err := NewDecoderFromBytes(append([]byte{0x10}, bytes.Repeat([]byte{0x11}, 2-1)...), nil).Decode()
+func TestFloat256NotEnoughData(t *testing.T) {
+ bin := append([]byte{0x14}, bytes.Repeat([]byte{0x11}, 32-1)...)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %s", err)
+ t.Fatal(err)
}
}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
"testing"
)
-func TestThrowsWhenUnknownTag(t *testing.T) {
- binstring := []byte{0x05}
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestUnknownTag(t *testing.T) {
+ _, err := NewDecoderFromBytes(append([]byte{0x05}, Junk...), nil).Decode()
if err != ErrUnknownType {
- t.Fatalf("expected ErrUnknownType, got %v", err)
+ t.Fatal(err)
}
}
-func TestThrowsWhenEmptyData(t *testing.T) {
+func TestEmptyData(t *testing.T) {
binstring := []byte{}
_, err := NewDecoderFromBytes(binstring, nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
+ t.Fatal(err)
}
}
func TestLonelyEOC(t *testing.T) {
- binstring := []byte{0x00}
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+ _, err := NewDecoderFromBytes(append([]byte{0x00}, Junk...), nil).Decode()
if err != ErrUnexpectedEOC {
- t.Fatalf("expected ErrUnexpectedEOC, got %v", err)
+ t.Fatal(err)
}
}
--- /dev/null
+package keks
+
+import (
+ "encoding/hex"
+)
+
+func mustHexDec(s string) []byte {
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "encoding/hex"
"io"
"math/big"
- "reflect"
"testing"
"testing/quick"
)
-func TestIntZero(t *testing.T) {
- object := 0
- binstring := mustHexDec("0C80")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestInt0(t *testing.T) {
+ obj := int(0)
+ bin := mustHexDec("0C80")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(uint64)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if casted != uint64(obj) {
+ t.Fatal("casted differs")
}
- if decoded != uint64(object) {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntOne(t *testing.T) {
- object := 1
- binstring := mustHexDec("0C8101")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestInt1(t *testing.T) {
+ obj := int(1)
+ bin := mustHexDec("0C8101")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ casted, ok := decoded.(uint64)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != uint64(obj) {
+ t.Fatal("casted differs")
}
- if decoded != uint64(object) {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntNegativeOne(t *testing.T) {
- object := -1
- binstring := mustHexDec("0D80")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestIntM1(t *testing.T) {
+ obj := int(-1)
+ bin := mustHexDec("0D80")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if decoded != int64(object) {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ casted, ok := decoded.(int64)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != int64(obj) {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestInt1s63Minus1(t *testing.T) {
- object := uint64(1<<63 - 1)
- binstring := mustHexDec("0c887fffffffffffffff")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestInt123(t *testing.T) {
+ obj := uint(123)
+ bin := mustHexDec("0C817B")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ casted, ok := decoded.(uint64)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != uint64(obj) {
+ t.Fatal("casted differs")
}
- if decoded != object {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestInt1s63(t *testing.T) {
- object, _ := big.NewInt(0).SetString("18446744073709551616", 10)
- binstring := mustHexDec("0c89010000000000000000")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestIntM123(t *testing.T) {
+ obj := int(-123)
+ bin := mustHexDec("0D817A")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
- t.Log(hex.EncodeToString(encoded))
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.(*big.Int)
+ casted, ok := decoded.(int64)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if udecoded.Cmp(object) != 0 {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if casted != int64(obj) {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestInt1s64(t *testing.T) {
- object := big.NewInt(1).SetBytes(mustHexDec("010000000000000000"))
- binstring := mustHexDec("0C89010000000000000000")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestIntMaxAllowable(t *testing.T) {
+ obj := uint64(1<<63) - 1
+ bin := mustHexDec("0C887FFFFFFFFFFFFFFF")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ casted, ok := decoded.(uint64)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != uint64(obj) {
+ t.Fatal("casted differs")
}
- if decoded.(*big.Int).Cmp(object) != 0 {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestInt1s130(t *testing.T) {
- object := big.NewInt(1).SetBytes(mustHexDec("0400000000000000000000000000000000"))
- binstring := mustHexDec("0C910400000000000000000000000000000000")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestIntNMaxAllowable(t *testing.T) {
+ obj := -int64(uint64(1<<63) - 1)
+ bin := mustHexDec("0D887FFFFFFFFFFFFFFE")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ casted, ok := decoded.(int64)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if decoded.(*big.Int).Cmp(object) != 0 {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntM1s62Plus1(t *testing.T) {
- object := int64(-9223372036854775808)
- binstring := mustHexDec("0D887FFFFFFFFFFFFFFF")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestInt64bit(t *testing.T) {
+ obj := big.NewInt(0)
+ obj = obj.SetBit(obj, 64, 1)
+ bin := mustHexDec("0C89010000000000000000")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(*big.Int)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if casted.Cmp(obj) != 0 {
+ t.Fatal("casted differs")
}
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestIntM64bit(t *testing.T) {
+ obj := big.NewInt(0)
+ obj = obj.SetBit(obj, 64, 1)
+ obj = obj.Neg(obj)
+ bin := mustHexDec("0D88FFFFFFFFFFFFFFFF")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.(int64)
+ casted, ok := decoded.(*big.Int)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if udecoded != object {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if casted.Cmp(obj) != 0 {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntM1s62(t *testing.T) {
- object, _ := big.NewInt(0).SetString("-9223372036854775809", 10)
- binstring := mustHexDec("0D888000000000000000")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestIntM64bitAnd1(t *testing.T) {
+ obj := big.NewInt(0)
+ obj = obj.SetBit(obj, 64, 1)
+ obj = obj.SetBit(obj, 0, 1)
+ obj = obj.Neg(obj)
+ bin := mustHexDec("0D89010000000000000000")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ casted, ok := decoded.(*big.Int)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted.Cmp(obj) != 0 {
+ t.Fatal("casted differs")
}
- if decoded.(*big.Int).Cmp(object) != 0 {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntM1s64(t *testing.T) {
- object := big.NewInt(0).SetBytes(mustHexDec("010000000000000000"))
- object = object.Neg(object)
- binstring := mustHexDec("0D88FFFFFFFFFFFFFFFF")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestInt131bit(t *testing.T) {
+ obj := big.NewInt(0)
+ obj = obj.SetBit(obj, 130, 1)
+ bin := mustHexDec("0C910400000000000000000000000000000000")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ casted, ok := decoded.(*big.Int)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if decoded.(*big.Int).Cmp(object) != 0 {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if casted.Cmp(obj) != 0 {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntM1s130(t *testing.T) {
- object := big.NewInt(1).SetBytes(mustHexDec("0100000000000000000000000000000000"))
- object = object.Neg(object)
- binstring := mustHexDec("0D90FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestIntM131bit(t *testing.T) {
+ obj := big.NewInt(0)
+ obj = obj.SetBit(obj, 130, 1)
+ obj = obj.Neg(obj)
+ bin := mustHexDec("0D9103FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+ casted, ok := decoded.(*big.Int)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if decoded.(*big.Int).Cmp(object) != 0 {
- t.Logf("expected type %s, value %d", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %d", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if casted.Cmp(obj) != 0 {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestIntThrowsWhenNotEnoughData(t *testing.T) {
+func TestIntNotEnoughData(t *testing.T) {
_, err := NewDecoderFromBytes(mustHexDec("0C830102"), nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected error, got %v", err)
+ t.Fatal(err)
}
_, err = NewDecoderFromBytes(mustHexDec("0C8301"), nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected error, got %v", err)
+ t.Fatal(err)
}
}
-func TestIntThrowsWhenNonMinimalInt(t *testing.T) {
+func TestIntNonMinimalInt(t *testing.T) {
encoded := mustHexDec("0C81007B")
_, err := NewDecoderFromBytes(encoded, nil).Decode()
if err != ErrIntNonMinimal {
- t.Fatalf("expected ErrIntNonMinimal, got %v", err)
+ t.Fatal(err)
}
}
-func TestIntThrowsWhenNonBinInInt(t *testing.T) {
+func TestIntNonBinInInt(t *testing.T) {
encoded := mustHexDec("0C017B")
_, err := NewDecoderFromBytes(encoded, nil).Decode()
if err != ErrBadInt {
- t.Fatalf("expected ErrBadInt, got %v", err)
- }
-}
-
-func TestInt64UnsignedSymmetric(t *testing.T) {
- f := func(x uint64) bool {
- encoded, err := EncodeBuf(x, nil)
- if err != nil {
- t.Logf("error during encode: %s", err)
- return false
- }
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
- if err != nil {
- t.Logf("error during decode: %s", err)
- return false
- }
- udecoded, ok := decoded.(uint64)
- if !ok {
- t.Logf("failed to cast")
- return false
- }
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
- }
- return true
- }
- if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt32UnsignedSymmetric(t *testing.T) {
- f := func(x uint32) bool {
+func TestInt64Symmetric(t *testing.T) {
+ f := func(x uint64) bool {
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uint64)
+ casted, ok := decoded.(uint64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == x
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt16UnsignedSymmetric(t *testing.T) {
- f := func(x uint16) bool {
- encoded, err := EncodeBuf(x, nil)
- if err != nil {
- t.Logf("error during encode: %s", err)
- return false
- }
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
- if err != nil {
- t.Logf("error during decode: %s", err)
- return false
- }
- udecoded, ok := decoded.(uint64)
- if !ok {
- t.Logf("failed to cast")
- return false
- }
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+func TestInt64NSymmetric(t *testing.T) {
+ f := func(x int64) bool {
+ if x >= 0 {
+ return true
}
- return true
- }
- if err := quick.Check(f, nil); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestInt8UnsignedSymmetric(t *testing.T) {
- f := func(x uint8) bool {
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uint64)
+ casted, ok := decoded.(int64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == x
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt32PositiveSymmetric(t *testing.T) {
- f := func(x int32) bool {
- if x == -1<<31 {
- return true
- }
- if x < 0 {
- x = -x
- }
+func TestInt32Symmetric(t *testing.T) {
+ f := func(x uint32) bool {
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uint64)
+ casted, ok := decoded.(uint64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == uint64(x)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt32NegativeSymmetric(t *testing.T) {
+func TestInt32NSymmetric(t *testing.T) {
f := func(x int32) bool {
- if x > 0 {
- x = -x
- }
- if x == 0 {
+ if x >= 0 {
return true
}
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(int64)
+ casted, ok := decoded.(int64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if int64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == int64(x)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt16PositiveSymmetric(t *testing.T) {
- f := func(x int16) bool {
- if x == -1<<15 {
- return true
- }
- if x < 0 {
- x = -x
- }
+func TestInt16Symmetric(t *testing.T) {
+ f := func(x uint16) bool {
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uint64)
+ casted, ok := decoded.(uint64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == uint64(x)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt16NegativeSymmetric(t *testing.T) {
+func TestInt16NSymmetric(t *testing.T) {
f := func(x int16) bool {
- if x > 0 {
- x = -x
- }
- if x == 0 {
+ if x >= 0 {
return true
}
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(int64)
+ casted, ok := decoded.(int64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if int64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == int64(x)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt8PositiveSymmetric(t *testing.T) {
- f := func(x int8) bool {
- if x == -1<<7 {
- return true
- }
- if x < 0 {
- x = -x
- }
+func TestInt8Symmetric(t *testing.T) {
+ f := func(x uint8) bool {
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uint64)
+ casted, ok := decoded.(uint64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == uint64(x)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt8NegativeSymmetric(t *testing.T) {
+func TestInt8NSymmetric(t *testing.T) {
f := func(x int8) bool {
- if x > 0 {
- x = -x
- }
- if x == 0 {
+ if x >= 0 {
return true
}
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(int64)
+ casted, ok := decoded.(int64)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if int64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == int64(x)
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt64PositiveSymmetric(t *testing.T) {
- f := func(x int64) bool {
- if x < 0 {
- x = -x
- }
+func TestIntBigSymmetric(t *testing.T) {
+ f := func(l uint8) bool {
+ data := make([]byte, 8+1+int(l))
+ if _, err := io.ReadFull(PRNG, data); err != nil {
+ panic(err)
+ }
+ data[0] |= 0x80 // be sure that is really a big number
+ x := big.NewInt(0).SetBytes(data)
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uint64)
+ casted, ok := decoded.(*big.Int)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if uint64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted.Cmp(x) == 0
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
}
}
-func TestInt64NegativeSymmetric(t *testing.T) {
- f := func(x int64) bool {
- if x > 0 {
- x = -x
- }
- if x == 0 {
- return true
- }
+func TestIntNBigSymmetric(t *testing.T) {
+ f := func(l uint8) bool {
+ data := make([]byte, 8+1+int(l))
+ if _, err := io.ReadFull(PRNG, data); err != nil {
+ panic(err)
+ }
+ data[0] |= 0x80 // be sure that is really a big number
+ x := big.NewInt(0).SetBytes(data)
+ x = x.Neg(x)
encoded, err := EncodeBuf(x, nil)
if err != nil {
- t.Logf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
-
+ t.Fatal(err)
}
- udecoded, ok := decoded.(int64)
+ casted, ok := decoded.(*big.Int)
if !ok {
- t.Logf("failed to cast")
- return false
+ t.Fatal("failed to cast")
}
- if int64(x) != udecoded {
- t.Logf("Expected <%s, %d>, got <%s, %d>", reflect.TypeOf(x), x, reflect.TypeOf(decoded), decoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted.Cmp(x) == 0
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
// GoKEKS -- Go KEKS codec implementation
-// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
package keks
import (
- "crypto/rand"
- "encoding/hex"
+ crand "crypto/rand"
"io"
- mrand "math/rand"
+ "math/rand/v2"
)
-func mustHexDec(s string) []byte {
- b, err := hex.DecodeString(s)
+var (
+ PRNG *rand.ChaCha8
+ Junk []byte
+)
+
+func init() {
+ var seed [32]byte
+ _, err := io.ReadFull(crand.Reader, seed[:])
if err != nil {
panic(err)
}
- return b
-}
-
-func invalidUTF8_2Byte(x, y int) []byte {
- return []byte{1<<7 | 1<<6 | byte(x), 1<<7 | 1<<6 | byte(y)}
-}
-
-func invalidUTF8_3Byte(x, y, z int) []byte {
- return []byte{(1<<7 | 1<<6 | 1<<5 | byte(x)), (1<<7 | byte(y)), (1<<7 | 1<<6 | byte(z))}
-}
-
-var Junk []byte
-
-func init() {
- Junk = make([]byte, 1+mrand.Intn(8))
- _, err := io.ReadFull(rand.Reader, Junk)
+ PRNG = rand.NewChaCha8(seed)
+ Junk = make([]byte, 1+rand.UintN(7))
+ _, err = io.ReadFull(PRNG, Junk)
if err != nil {
panic(err)
}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "encoding/hex"
"io"
- "reflect"
+ "math/rand/v2"
"slices"
"testing"
"testing/quick"
)
func TestListEmpty(t *testing.T) {
- object := []any{}
- binstring := []byte("\x08\x00")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+ obj := []any{}
+ bin := []byte{0x08, 0x00}
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during encode: %s", err)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- udecoded, ok := decoded.([]any)
+ casted, ok := decoded.([]any)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if !slices.Equal(obj, casted) {
+ t.Fatal("casted differs")
}
- if !slices.Equal(object, udecoded) {
- t.Logf("expected type %s, value true", reflect.TypeOf(object))
- t.Logf("got type %s, value %t", reflect.TypeOf(decoded), decoded)
- t.FailNow()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestListThrowsWhenNoEOC(t *testing.T) {
- binstring := []byte("\x08")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestListNoEOC(t *testing.T) {
+ encoded, err := EncodeBuf([]int{123}, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = NewDecoderFromBytes(encoded[:len(encoded)-1], nil).Decode()
if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
+ t.Fatal(err)
+ }
+}
+
+func TestListMaxContLen(t *testing.T) {
+ l := 2 + rand.UintN(8)
+ bin, err := EncodeBuf(make([]int, l), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder := NewDecoderFromBytes(bin, nil)
+ _, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder = NewDecoderFromBytes(bin, &DecodeOpts{MaxContLen: int64(l) + 1})
+ _, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder = NewDecoderFromBytes(bin, &DecodeOpts{MaxContLen: int64(l)})
+ _, err = decoder.Decode()
+ if err != ErrLenTooBig {
+ t.Fatal(err)
}
}
func TestListIntSymmetric(t *testing.T) {
- f := func(x []uint64) bool {
- encoded, err := EncodeBuf(x, nil)
+ f := func(vs []int64) bool {
+ encoded, err := EncodeBuf(vs, nil)
if err != nil {
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.([]any)
+ casted, ok := decoded.([]any)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
}
- if len(x) != len(udecoded) {
+ if len(vs) != len(casted) {
return false
}
- for i := range x {
- if x[i] != udecoded[i] {
- t.Logf("Expected <%s, %d>", reflect.TypeOf(x), x)
- t.Logf("Instead <%s, %d>", reflect.TypeOf(decoded), decoded)
+ for i := range len(vs) {
+ switch v := casted[i].(type) {
+ case uint64:
+ if v != uint64(vs[i]) {
+ return false
+ }
+ case int64:
+ if v != int64(vs[i]) {
+ return false
+ }
+ default:
return false
}
}
--- /dev/null
+// GoKEKS -- Go KEKS codec implementation
+// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, version 3 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package keks
+
+import (
+ "bytes"
+ "io"
+ "strings"
+ "testing"
+ "testing/quick"
+)
+
+func TestMagicSymmetric(t *testing.T) {
+ f := func(m [12]byte) bool {
+ encoded, err := EncodeBuf(Magic(m[:]), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ casted, ok := decoded.(Magic)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+ return string(casted) == strings.TrimRight(string(m[:]), "\x00")
+ }
+ if err := quick.Check(f, nil); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestMagicNotEnoughData(t *testing.T) {
+ encoded, err := EncodeBuf(Magic("something"), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder := NewDecoderFromBytes(encoded[:len(encoded)-1], nil)
+ _, err = decoder.Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
+ }
+}
+
+func TestMagicBadMagic(t *testing.T) {
+ encoded, err := EncodeBuf(Magic("something"), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded[2] = 'e'
+ decoder := NewDecoderFromBytes(encoded, nil)
+ _, err = decoder.Decode()
+ if err != ErrBadMagic {
+ t.Fatal(err)
+ }
+}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "encoding/hex"
- "maps"
- "reflect"
+ "math/rand/v2"
+ "strconv"
"testing"
"testing/quick"
)
func TestMapEmpty(t *testing.T) {
- binstring := []byte("\x09\x00")
- object := make(map[string]any)
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+ bin := []byte("\x09\x00")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(object, nil)
+ encoded, err := EncodeBuf(struct{}{}, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
}
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- udecoded, ok := decoded.(map[string]any)
+ casted, ok := decoded.(map[string]any)
if !ok {
- t.Fatalf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if len(casted) != 0 {
+ t.Fatal("casted differs")
}
- if !maps.Equal(object, udecoded) {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.Fail()
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
}
-func TestMapThrowsWhenNonStringKey(t *testing.T) {
- object := make(map[any]any)
- object[1] = "a"
- binstring := []byte("\x09\x0C\x80\xC6value2\x00")
- _, err := EncodeBuf(object, nil)
+func TestMapEncodeNonStrKey(t *testing.T) {
+ _, err := EncodeBuf(map[any]any{123: 123}, nil)
if err != ErrMapBadKey {
- t.Fatalf("expected ErrMapBadKey during encode, got %v", err)
+ t.Fatal(err)
}
- _, err = NewDecoderFromBytes(binstring, nil).Decode()
+}
+
+func TestMapDecodeNonStrKey(t *testing.T) {
+ _, err := NewDecoderFromBytes([]byte("\x09\x0C\x80\xC6value2\x00"), nil).Decode()
if err != ErrMapBadKey {
- t.Fatalf("expected ErrMapBadKey during decode, got %v", err)
+ t.Fatal(err)
}
}
-func TestMapThrowsWhenUnexpectedEOC(t *testing.T) {
- binstring := []byte("\x09\xC4key1\x00\x00")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestMapUnexpectedEOC(t *testing.T) {
+ _, err := NewDecoderFromBytes([]byte("\x09\xC4key1\x00\x00"), nil).Decode()
if err != ErrUnexpectedEOC {
- t.Fatalf("expected ErrUnexpectedEOC during decode, got %v", err)
+ t.Fatal(err)
}
}
-func TestMapThrowsWhenEmptyStringKeyEncode(t *testing.T) {
- object := make(map[any]any)
- object[""] = "a"
- _, err := EncodeBuf(object, nil)
+func TestMapEncodeEmptyStrKey(t *testing.T) {
+ _, err := EncodeBuf(map[string]any{"": 123}, nil)
if err != ErrMapBadKey {
- t.Fatalf("expected ErrMapBadKey during encode, got %v", err)
+ t.Fatal(err)
}
}
-func TestMapThrowsWhenEmptyStringKeyDecode(t *testing.T) {
- binstring := []byte("\x09\xC0\x0C\x81\x01\xC4key1\xC6value1\x00")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestMapDecodeEmptyStrKey(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec("09C0C000"), nil).Decode()
if err != ErrMapBadKey {
- t.Fatalf("expected ErrMapBadKey during decode, got %v", err)
+ t.Fatal(err)
+ }
+}
+
+func TestMapUnsortedValueKeys(t *testing.T) {
+ bin := bytes.Join([][]byte{
+ mustHexDec("09"),
+ mustHexDec("C4"), []byte("key2"),
+ mustHexDec("0C8101"),
+ mustHexDec("C4"), []byte("key1"),
+ mustHexDec("C6"), []byte("value1"),
+ mustHexDec("00"),
+ }, nil)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrMapUnordered {
+ t.Fatal(err)
}
}
-func TestMapThrowsWhenUnsortedKeys(t *testing.T) {
- binstring := []byte("\x09\xC4key2\xC6value2\xC4key1\xC6value1\x00")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestMapUnsortedLenKeys(t *testing.T) {
+ bin := bytes.Join([][]byte{
+ mustHexDec("09"),
+ mustHexDec("C4"), []byte("key2"),
+ mustHexDec("0C8101"),
+ mustHexDec("C3"), []byte("key"),
+ mustHexDec("C6"), []byte("value1"),
+ mustHexDec("00"),
+ }, nil)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != ErrMapUnordered {
- t.Fatalf("expected ErrMapUnordered during decode, got %v", err)
+ t.Fatal(err)
+ }
+}
+
+func TestMapMaxContLen(t *testing.T) {
+ l := 2 + rand.UintN(8)
+ m := make(map[string]int, l)
+ for i := range l {
+ m[strconv.Itoa(int(i))] = 123
+ }
+ bin, err := EncodeBuf(m, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder := NewDecoderFromBytes(bin, nil)
+ _, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder = NewDecoderFromBytes(bin, &DecodeOpts{MaxContLen: int64(l) + 1})
+ _, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder = NewDecoderFromBytes(bin, &DecodeOpts{MaxContLen: int64(l)})
+ _, err = decoder.Decode()
+ if err != ErrLenTooBig {
+ t.Fatal(err)
}
}
func TestMapIntSymmetric(t *testing.T) {
- f := func(x map[string]uint64) bool {
- delete(x, "")
- encoded, err := EncodeBuf(x, nil)
+ f := func(m map[int]uint64) bool {
+ obj := make(map[string]uint64, len(m))
+ for k, v := range m {
+ obj[strconv.Itoa(k)] = v
+ }
+ m = nil
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(map[string]any)
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+ casted, ok := decoded.(map[string]any)
if !ok {
- t.Logf("failed to cast")
+ t.Fatal("failed to cast")
+ }
+ if len(casted) != len(obj) {
return false
}
- for k := range x {
- if x[k] != udecoded[k] {
- t.Logf("expected <%s, %v>", reflect.TypeOf(x), x)
- t.Logf("instead <%s, %v>", reflect.TypeOf(udecoded), udecoded)
+ for k := range obj {
+ v, ok := casted[k]
+ if !ok {
+ return false
+ }
+ i, ok := v.(uint64)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if i != obj[k] {
return false
}
}
return
}
count++
+ if ctx.opts != nil &&
+ ctx.opts.MaxContLen > 0 &&
+ int64(count) >= ctx.opts.MaxContLen {
+ err = ErrLenTooBig
+ return
+ }
}
ctx.lens[idx] = count
ctx.depth--
--- /dev/null
+// GoKEKS -- Go KEKS codec implementation
+// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, version 3 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package keks
+
+import (
+ "bytes"
+ "io"
+ "math/rand"
+ "reflect"
+ "strings"
+ "testing"
+ "testing/quick"
+
+ "go.cypherpunks.su/keks/be"
+)
+
+func TestStrEmpty(t *testing.T) {
+ obj := ""
+ bin := mustHexDec("C0")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestStrHelloWorld(t *testing.T) {
+ obj := "hello world"
+ bin := append([]byte{0xCB}, []byte("hello world")...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestStrПриветМир(t *testing.T) {
+ obj := "привет мир"
+ bin := append([]byte{0xD3}, []byte("привет мир")...)
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestStrLen62(t *testing.T) {
+ obj := strings.Repeat("a", 62)
+ bin := mustHexDec("FD01" + strings.Repeat("61", 62))
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestStrLen318(t *testing.T) {
+ obj := strings.Repeat("a", 62+255+1)
+ bin := mustHexDec("FE0001" + strings.Repeat("61", 62+255+1))
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestStrLen65853(t *testing.T) {
+ obj := strings.Repeat("a", 62+255+65535+1)
+ bin := mustHexDec("FF0000000000000000" + strings.Repeat("61", 62+255+65535+1))
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ encoded, err := EncodeBuf(obj, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if casted != obj {
+ t.Fatal("casted differs")
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+}
+
+func TestStrNullByteInUTF8(t *testing.T) {
+ bin := []byte("\xC5he\x00\x01\x02")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrBadUTF8 {
+ t.Fatal(err)
+ }
+}
+
+func TestStrNullByteInUTF8AndCheckDisabled(t *testing.T) {
+ bin := []byte("\xC5he\x00\x01\x02")
+ _, err := NewDecoderFromBytes(bin, &DecodeOpts{DisableUTF8Check: true}).Decode()
+ if err == ErrBadUTF8 {
+ t.Fatal(err)
+ }
+}
+
+// Here go invalid UTF-8 byte(s) strategies. We can fail in following
+// ways during decoding:
+// * invalid start byte -- hypothesis generates integers that will
+// satisfy that fail
+// * invalid continuation byte -- we strip last byte of multibyte
+// sequences
+// * unexpected end of data -- we strip the last byte of our data
+
+func TestStrStripped2ByteInUTF8(t *testing.T) {
+ // 110xxxxx 10xxxxxx(STRIPPED)
+ f := func(x int) bool {
+ bin := []byte{0xC1, (1 << 7) | (1 << 6) | byte(x)}
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrBadUTF8 {
+ return false
+ }
+ _, err = NewDecoderFromBytes(bin,
+ &DecodeOpts{DisableUTF8Check: true}).Decode()
+ return err == nil
+ }
+ if err := quick.Check(f, &quick.Config{
+ Values: func(v []reflect.Value, r *rand.Rand) {
+ v[0] = reflect.ValueOf(r.Intn((1 << 5) - 1))
+ },
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestStrStripped3ByteInUTF8(t *testing.T) {
+ // 1110xxxx 10xxxxxx 10xxxxxx(STRIPPED)
+ f := func(x int) bool {
+ bin := []byte{
+ 0xC2,
+ (1 << 7) | (1 << 6) | (1 << 5) | byte(x>>6),
+ byte((1 << 7) | (((1 << 6) - 1) & x)),
+ }
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrBadUTF8 {
+ return false
+ }
+ _, err = NewDecoderFromBytes(bin,
+ &DecodeOpts{DisableUTF8Check: true}).Decode()
+ return err == nil
+ }
+ if err := quick.Check(f, &quick.Config{
+ Values: func(v []reflect.Value, r *rand.Rand) {
+ v[0] = reflect.ValueOf(r.Intn((1 << 10) - 1))
+ },
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestStrNotEnoughData(t *testing.T) {
+ bin, err := EncodeBuf("hello", nil)
+ if err != nil {
+ panic(err)
+ }
+ _, err = NewDecoderFromBytes(bin[:len(bin)-1], nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
+ }
+}
+
+func TestStrNotEnoughDataForLength8(t *testing.T) {
+ bin, err := EncodeBuf(strings.Repeat("f", 100), nil)
+ if err != nil {
+ panic(err)
+ }
+ _, err = NewDecoderFromBytes(bin[:len(bin)-1], nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
+ }
+}
+
+func TestStrNotEnoughDataForLength16(t *testing.T) {
+ bin, err := EncodeBuf(strings.Repeat("f", 318), nil)
+ if err != nil {
+ panic(err)
+ }
+ _, err = NewDecoderFromBytes(bin[:len(bin)-1], nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
+ }
+}
+
+func TestStrNotEnoughDataForLength64(t *testing.T) {
+ bin, err := EncodeBuf(strings.Repeat("f", 65853), nil)
+ if err != nil {
+ panic(err)
+ }
+ _, err = NewDecoderFromBytes(bin[:len(bin)-1], nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
+ }
+}
+
+func TestStrTooLong(t *testing.T) {
+ bin := make([]byte, 9)
+ bin[0] = 0xFF
+ for _, l := range []uint64{
+ 1 << 63,
+ (1 << 63) - 63,
+ (1 << 63) - 63 - ((1 << 8) - 1),
+ (1 << 63) - 63 - ((1 << 8) - 1) - ((1 << 16) - 1) + 1,
+ } {
+ be.Put(bin[1:], l)
+ decoder := NewDecoderFromBytes(bin, nil)
+ _, err := decoder.Decode()
+ if err != ErrLenTooBig {
+ t.Fatal(err)
+ }
+ }
+}
+
+func TestStrNotTooLong(t *testing.T) {
+ bin := make([]byte, 9)
+ bin[0] = 0xFF
+ be.Put(bin[1:], (1<<63)-63-((1<<8)-1)-((1<<16)-1))
+ decoder := NewDecoderFromReader(bytes.NewReader(bin), nil)
+ defer func() { recover() }()
+ _, err := decoder.Decode()
+ // it won't reach that code because it can not allocate so much
+ // memory in .getBytes(), but that means, that no error was returned
+ t.Fatal(err)
+}
+
+func TestStrMaxStrLen(t *testing.T) {
+ f := func(str string) bool {
+ if str == "" {
+ return true
+ }
+ encoded, err := EncodeBuf(str, nil)
+ if err != nil {
+ panic(err)
+ }
+ decoder := NewDecoderFromBytes(encoded,
+ &DecodeOpts{DisableUTF8Check: true, MaxStrLen: int64(len(str) + 1)})
+ _, err = decoder.Decode()
+ if err != nil {
+ return false
+ }
+ decoder = NewDecoderFromBytes(encoded,
+ &DecodeOpts{DisableUTF8Check: true, MaxStrLen: int64(len(str))})
+ _, err = decoder.Decode()
+ if err != nil {
+ return false
+ }
+ if len(str) == 1 {
+ return true
+ }
+ decoder = NewDecoderFromBytes(encoded,
+ &DecodeOpts{DisableUTF8Check: true, MaxStrLen: int64(len(str) - 1)})
+ _, err = decoder.Decode()
+ return err != nil
+ }
+ if err := quick.Check(f, nil); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestStrSymmetric(t *testing.T) {
+ f := func(str string) bool {
+ encoded, err := EncodeBuf(str, nil)
+ if err != nil {
+ panic(err)
+ }
+ decoder := NewDecoderFromBytes(
+ append(encoded, Junk...),
+ &DecodeOpts{DisableUTF8Check: true},
+ )
+ decoded, err := decoder.Decode()
+ if err != nil {
+ return false
+ }
+ casted, ok := decoded.(string)
+ if !ok {
+ return false
+ }
+ if str != casted {
+ return false
+ }
+ return bytes.Equal(decoder.B, Junk)
+ }
+ if err := quick.Check(f, nil); err != nil {
+ t.Fatal(err)
+ }
+}
+++ /dev/null
-// GoKEKS -- Go KEKS codec implementation
-// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as
-// published by the Free Software Foundation, version 3 of the License.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-package keks
-
-import (
- "bytes"
- "encoding/hex"
- "io"
- mrand "math/rand"
- "reflect"
- "strings"
- "testing"
- "testing/quick"
-)
-
-func TestStrEmpty(t *testing.T) {
- object := ""
- binstring := mustHexDec("C0")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- encoded, err := EncodeBuf(object, nil)
- if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
- }
- if decoded != object {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
- }
-}
-
-func TestStrHelloWorld(t *testing.T) {
- object := "hello world"
- binstring := bytes.Join([][]byte{mustHexDec("CB"), []byte("hello world")}, nil)
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- encoded, err := EncodeBuf(object, nil)
- if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
- }
- if decoded != object {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
- }
-}
-
-func TestStrRuHelloWorld(t *testing.T) {
- object := "привет мир"
- binstring := bytes.Join([][]byte{mustHexDec("D3"), []byte("привет мир")}, nil)
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- encoded, err := EncodeBuf(object, nil)
- if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
- }
- if decoded != object {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
- }
-}
-
-func TestStrLen62(t *testing.T) {
- object := strings.Repeat("a", 62)
- binstring := mustHexDec(
- strings.Join([]string{"FD01", strings.Repeat("61", 62)}, ""),
- )
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- encoded, err := EncodeBuf(object, nil)
- if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
- }
- if decoded != object {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
- }
-}
-
-func TestStrLen318(t *testing.T) {
- object := strings.Repeat("a", 318)
- binstring := mustHexDec(
- strings.Join([]string{"FE0001", strings.Repeat("61", 318)}, ""),
- )
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- encoded, err := EncodeBuf(object, nil)
- if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected binstring %s, got %s", hex.EncodeToString(binstring), hex.EncodeToString(encoded))
- }
- if decoded != object {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
- }
-}
-
-func TestStrLen65853(t *testing.T) {
- object := strings.Repeat("a", 65853)
- binstring := mustHexDec(
- strings.Join([]string{"FF0000000000000000", strings.Repeat("61", 65853)}, ""),
- )
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
- }
- encoded, err := EncodeBuf(object, nil)
- if err != nil {
- t.Fatalf("error during encode: %s", err)
- }
- if !bytes.Equal(encoded, binstring) {
- t.Logf("expected binstring to begin with %s, got %s", hex.EncodeToString(binstring)[:40], hex.EncodeToString(encoded)[:40])
- t.Fail()
- }
- if decoded != object {
- t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
- t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
- t.FailNow()
- }
-}
-
-func TestStrThrowsWhenNullByteInUTF8(t *testing.T) {
- binstring := []byte("\xC5he\x00\x01\x02")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrBadUTF8 {
- t.Fatalf("expected ErrBadUTF8, got %v", err)
- }
-}
-
-func TestStrOkWhenNullByteInUTF8AndUTF8CheckDisabled(t *testing.T) {
- binstring := []byte("\xC5he\xe2\x82\x28")
- _, err := NewDecoderFromBytes(binstring, &DecodeOpts{DisableUTF8Check: true}).Decode()
- if err != nil {
- t.Fatalf("error during decode: %v", err)
- }
-}
-
-func TestStrThrowsWhenInvalid2BytesInUTF8(t *testing.T) {
- f := func(x, y int) bool {
- binstring := bytes.Join([][]byte{[]byte("\xC2"), invalidUTF8_2Byte(x, y)}, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrBadUTF8 {
- t.Logf("expected ErrBadUTF8, got %v", err)
- return false
- }
- return true
- }
- if err := quick.Check(f, &quick.Config{
- Values: func(v []reflect.Value, r *mrand.Rand) {
- v[0] = reflect.ValueOf(r.Intn(1 << 5))
- v[1] = reflect.ValueOf(r.Intn(1 << 5))
- },
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestStrOkWhenInvalid2BytesInUTF8AndUTF8CheckDisabled(t *testing.T) {
- f := func(x, y int) bool {
- _, err := NewDecoderFromBytes(bytes.Join([][]byte{[]byte("\xC2"), invalidUTF8_2Byte(x, y)}, nil), &DecodeOpts{DisableUTF8Check: true}).Decode()
- if err != nil {
- t.Logf("error during decode: %v", err)
- return false
- }
- return true
- }
- if err := quick.Check(f, &quick.Config{
- Values: func(v []reflect.Value, r *mrand.Rand) {
- v[0] = reflect.ValueOf(r.Intn(1 << 5))
- v[1] = reflect.ValueOf(r.Intn(1 << 5))
- },
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestStrThrowsWhenInvalid3BytesInUTF8(t *testing.T) {
- f := func(x, y, z int) bool {
- binstring := bytes.Join([][]byte{[]byte("\xC3"), invalidUTF8_3Byte(x, y, z)}, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrBadUTF8 {
- t.Logf("expected ErrBadUTF8, got %v", err)
- return false
- }
- return true
- }
- if err := quick.Check(f, &quick.Config{
- Values: func(v []reflect.Value, r *mrand.Rand) {
- v[0] = reflect.ValueOf(r.Intn(1 << 4))
- v[1] = reflect.ValueOf(r.Intn(1 << 6))
- v[2] = reflect.ValueOf(r.Intn(1 << 6))
- },
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestStrOkWhenInvalid3BytesInUTF8AndUTF8CheckDisabled(t *testing.T) {
- f := func(x, y, z int) bool {
- binstring := bytes.Join([][]byte{[]byte("\xC3"), invalidUTF8_3Byte(x, y, z)}, nil)
- _, err := NewDecoderFromBytes(binstring, &DecodeOpts{DisableUTF8Check: true}).Decode()
- if err != nil {
- t.Logf("error during decode: %v", err)
- return false
- }
- return true
- }
- if err := quick.Check(f, &quick.Config{
- Values: func(v []reflect.Value, r *mrand.Rand) {
- v[0] = reflect.ValueOf(r.Intn(1 << 4))
- v[1] = reflect.ValueOf(r.Intn(1 << 6))
- v[2] = reflect.ValueOf(r.Intn(1 << 6))
- },
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestStrThrowsWhenNotEnoughData(t *testing.T) {
- binstring := []byte("\xC5he")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
- }
-}
-
-func TestStrThrowsWhenNotEnoughDataForLength8(t *testing.T) {
- binstring := []byte("\xC5he")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
- }
-}
-
-func TestStrThrowsWhenNotEnoughDataForLength16(t *testing.T) {
- binstring := []byte("\xC5he")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
- }
-}
-
-func TestThrowsWhenNotEnoughDataForLength64(t *testing.T) {
- binstring := []byte("\xC5he")
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != io.ErrUnexpectedEOF {
- t.Fatalf("expected io.ErrUnexpectedEOF, got %v", err)
- }
-}
-
-func TestStrThrowsWhenStringTooLong(t *testing.T) {
- f := func(str string, y uint8) bool {
- if str == "" {
- return true
- }
- y = y % uint8(len(str))
- if y == 0 {
- return true
- }
- encoded, _ := EncodeBuf(str, nil)
- decoder := NewDecoderFromBytes(encoded, &DecodeOpts{MaxStrLen: int64(len(str) - int(y))})
- _, err := decoder.Decode()
- if err != ErrLenTooBig {
- t.Logf("expected ErrLenTooBig, got %v", err)
- return false
- }
- return true
- }
- if err := quick.Check(f, nil); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestStrOkWhenMaxStrLenSet(t *testing.T) {
- f := func(str string, y uint8) bool {
- encoded, err := EncodeBuf(str, nil)
- if err != nil {
- return false
- }
- decoder := NewDecoderFromBytes(encoded, &DecodeOpts{MaxStrLen: int64(len(str) + int(y))})
- decoded, err := decoder.Decode()
- if err != nil {
- return false
- }
- if str != decoded.(string) {
- t.Logf("Expected <%s, %s>", reflect.TypeOf(str), str)
- t.Logf("Instead <%s, %s>", reflect.TypeOf(decoded), decoded)
- return false
- }
- return true
- }
- if err := quick.Check(f, nil); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestStrSymmetric(t *testing.T) {
- f := func(str string) bool {
- encoded, err := EncodeBuf(str, nil)
- if err != nil {
- return false
- }
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
- if err != nil {
- return false
- }
- if str != decoded.(string) {
- t.Logf("Expected <%s, %s>", reflect.TypeOf(str), str)
- t.Logf("Instead <%s, %s>", reflect.TypeOf(decoded), decoded)
- return false
- }
- return true
- }
- if err := quick.Check(f, nil); err != nil {
- t.Fatal(err)
- }
-}
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
+ "io"
+ "strings"
"testing"
"testing/quick"
"time"
+
+ "go.cypherpunks.su/keks/be"
+ "go.cypherpunks.su/tai64n/v4"
)
-func TestTai64LargeNumberOfSeconds(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("18"),
- mustHexDec("7000000065195F65"),
- }, nil)
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+const hex1G = "3B9ACA00" // one billion
+
+func TestTAINotEnoughData(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "18"+strings.Repeat("0", 2*8-2)), nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during encode: %s", err)
+}
+
+func TestTAINNotEnoughData(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "19"+strings.Repeat("0", 2*12-2)), nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
}
- t.Log(decoded)
}
-func TestTai64NLargeNumberOfSeconds(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("19"),
- mustHexDec("7000000065195F65"),
- mustHexDec("3B9AC9FF"),
- }, nil)
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != nil {
- t.Fatalf("error during decode: %s", err)
+func TestTAINANotEnoughData(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "1A"+strings.Repeat("0", 2*16-2)), nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
}
+}
+
+func TestTAILargeNumberOfSeconds(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "18"+"7000000065195F65"), nil).Decode()
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- t.Log(decoded)
}
-func TestTai64NALargeNumberOfSeconds(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("1A"),
- mustHexDec("7000000065195F66"),
- mustHexDec("3B9AC9FF"),
- mustHexDec("3B9AC9FF"),
- }, nil)
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAINLargeNumberOfSeconds(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "19"+"7000000065195F65"+"00010000"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
+}
+
+func TestTAINALargeNumberOfSeconds(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "1A"+"7000000065195F65"+"00010000"+"00010000"), nil).Decode()
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- t.Log(decoded)
}
-func TestTaiThrowsWhenMsbIsSet(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("18"),
- mustHexDec("8000000065195F65"),
- }, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrTaiReserved {
- t.Fatalf("expected 'reserved TAI64 value is in use', got %v", err)
+func TestTAIMsbIsSet(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "18"+"8000000065195F65"), nil).Decode()
+ if err != ErrTAIReserved {
+ t.Fatal(err)
+ }
+}
+
+func TestTAINMsbIsSet(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "19"+"8000000065195F65"+"00010000"), nil).Decode()
+ if err != ErrTAIReserved {
+ t.Fatal(err)
+ }
+}
+
+func TestTAINAMsbIsSet(t *testing.T) {
+ _, err := NewDecoderFromBytes(mustHexDec(
+ "19"+"8000000065195F65"+"00010000"+"00010000"), nil).Decode()
+ if err != ErrTAIReserved {
+ t.Fatal(err)
}
}
-func TestTai64NThrowsWhenTooManyNanosecs(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("19"),
- mustHexDec("4000000000000000"),
- mustHexDec("3B9ACA00"),
- }, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAINTooManyNanosecs(t *testing.T) {
+ bin := mustHexDec("19" + "4000000000000000" + hex1G)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != ErrTooManyNsecs {
- t.Fatalf("expected 'too many nanoseconds', got %v", err)
+ t.Fatal(err)
}
}
-func TestTai64NThrowsWhenZeroNanoseconds(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("19"),
- mustHexDec("4000000000000000"),
- mustHexDec("00000000"),
- }, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrTaiNonMinimal {
- t.Fatalf("expected 'non-minimal TAI64N', got %v", err)
+func TestTAINATooManyNanosecs(t *testing.T) {
+ bin := mustHexDec("1A" + "4000000000000000" + hex1G + "00010000")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrTooManyNsecs {
+ t.Fatal(err)
}
}
-func TestTai64NAThrowsWhenTooManyAttoseconds(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("1A"),
- mustHexDec("4000000000000000"),
- mustHexDec("00000000"),
- mustHexDec("3B9ACA00"),
- }, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAINATooManyAttosecs(t *testing.T) {
+ bin := mustHexDec("1A" + "4000000000000000" + "00010000" + hex1G)
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != ErrTooManyAsecs {
- t.Fatalf("expected 'too many attoseconds', got %v", err)
+ t.Fatal(err)
}
}
-func TestTai64NAThrowsWhenZeroAttoseconds(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("1A"),
- mustHexDec("4000000000000000"),
- mustHexDec("00000000"),
- mustHexDec("00000000"),
- }, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrTaiNonMinimal {
- t.Fatalf("expected 'non-minimal TAI64NA', got %v", err)
+func TestTAINZeroNanosecs(t *testing.T) {
+ bin := mustHexDec("19" + "4000000000000000" + "00000000")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrTAINonMinimal {
+ t.Fatal(err)
}
}
-func TestTai64NAZeroNanosecondsOk(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("1A"),
- mustHexDec("4000000000000000"),
- mustHexDec("00000000"),
- mustHexDec("00000001"),
- }, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAINAZeroNanosecsOk(t *testing.T) {
+ bin := mustHexDec("1A" + "4000000000000000" + "00000000" + "00000001")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
if err != nil {
- t.Fatalf("expected no error, got %v", err)
+ t.Fatal(err)
}
}
-func TestTai64NAThrowsWhenMsbIsSet(t *testing.T) {
- binstring := bytes.Join([][]byte{
- mustHexDec("1A"),
- mustHexDec("8000000065195F65"),
- mustHexDec("00000001"),
- mustHexDec("00000001")}, nil)
- _, err := NewDecoderFromBytes(binstring, nil).Decode()
- if err != ErrTaiReserved {
- t.Fatalf("expected 'reserved TAI64 value is in use', got %v", err)
+func TestTAINAZeroAttosecs(t *testing.T) {
+ bin := mustHexDec("1A" + "4000000000000000" + "00000000" + "00000000")
+ _, err := NewDecoderFromBytes(bin, nil).Decode()
+ if err != ErrTAINonMinimal {
+ t.Fatal(err)
}
}
-func TestTai19700101(t *testing.T) {
- binstring := mustHexDec("18400000000000000A")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAI19700101(t *testing.T) {
+ decoded, err := NewDecoderFromBytes(mustHexDec(
+ "18400000000000000A"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during decode: %v", err)
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
}
- expected := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)
- decodedTime := decoded.(time.Time)
- if !decodedTime.Equal(expected) {
- t.Fatalf("expected %v, got %v", expected, decoded)
+ if !casted.Equal(time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)) {
+ t.Fatal("casted differs")
}
}
-func TestTai19920602(t *testing.T) {
- binstring := mustHexDec("18400000002A2B2C2D")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAI19920602(t *testing.T) {
+ decoded, err := NewDecoderFromBytes(mustHexDec(
+ "18400000002A2B2C2D"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- decodedTime := decoded.(time.Time)
- if err != nil {
- t.Fatalf("error during decode: %v", err)
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
}
- expected := time.Date(1992, 6, 2, 8, 6, 43, 0, time.UTC)
- if !decodedTime.Equal(expected) {
- t.Fatalf("expected %v, got %v", expected, decoded)
+ if !casted.Equal(time.Date(1992, 6, 2, 8, 6, 43, 0, time.UTC)) {
+ t.Fatal("casted differs")
}
}
-func TestTai19971003(t *testing.T) {
- binstring := mustHexDec("184000000034353637")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAI19971003(t *testing.T) {
+ decoded, err := NewDecoderFromBytes(mustHexDec(
+ "184000000034353637"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- decodedTime := decoded.(time.Time)
- if err != nil {
- t.Fatalf("error during decode: %v", err)
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
}
- expected := time.Date(1997, 10, 3, 18, 14, 48, 0, time.UTC)
- if !decodedTime.Equal(expected) {
- t.Fatalf("expected %v, got %v", expected, decoded)
+ if !casted.Equal(time.Date(1997, 10, 3, 18, 14, 48, 0, time.UTC)) {
+ t.Fatal("casted differs")
}
}
-func TestTai20161231(t *testing.T) {
- binstring := mustHexDec("1840000000586846A3")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAI20161231(t *testing.T) {
+ decoded, err := NewDecoderFromBytes(mustHexDec(
+ "1840000000586846A3"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- decodedTime := decoded.(time.Time)
- if err != nil {
- t.Fatalf("error during decode: %v", err)
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
}
- expected := time.Date(2016, 12, 31, 23, 59, 59, 0, time.UTC)
- if !decodedTime.Equal(expected) {
- t.Fatalf("expected %v, got %v", expected, decoded)
+ if !casted.Equal(time.Date(2016, 12, 31, 23, 59, 59, 0, time.UTC)) {
+ t.Fatal("casted differs")
}
}
-func TestTai20170101(t *testing.T) {
- binstring := mustHexDec("1840000000586846A5")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAI20170101(t *testing.T) {
+ decoded, err := NewDecoderFromBytes(mustHexDec(
+ "1840000000586846A5"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- decodedTime := decoded.(time.Time)
- if err != nil {
- t.Fatalf("error during decode: %v", err)
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
}
- expected := time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC)
- if !decodedTime.Equal(expected) {
- t.Fatalf("expected %v, got %v", expected, decoded)
+ if !casted.Equal(time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC)) {
+ t.Fatal("casted differs")
}
}
-func TestTai20241120(t *testing.T) {
- binstring := mustHexDec("1940000000673DD3E136F11FE0")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+func TestTAI20241120(t *testing.T) {
+ decoded, err := NewDecoderFromBytes(mustHexDec(
+ "1940000000673DD3E136F11FE0"), nil).Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- decodedTime := decoded.(time.Time)
- if err != nil {
- t.Fatalf("error during decode: %v", err)
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
}
- expected := time.Date(2024, 11, 20, 12, 19, 8, 921772000, time.UTC)
- if !decodedTime.Equal(expected) {
- t.Fatalf("expected %v, got %v", expected, decoded)
+ if !casted.Equal(time.Date(2024, 11, 20, 12, 19, 8, 921772000, time.UTC)) {
+ t.Fatal("casted differs")
}
}
-func TestTaiSymmetric(t *testing.T) {
- f := func(a, b int64) bool {
- x := time.Unix(a, b)
- if a > 1<<62-1 {
+func TestTAISymmetric(t *testing.T) {
+ f := func(secs int64) bool {
+ if (secs > (1<<62)-1) || (secs < -(1 << 62)) {
return true
}
- if a < -1<<62 {
- return true
+ tm := time.Unix(secs, 0)
+ encoded, err := EncodeBuf(tm, nil)
+ if err != nil {
+ t.Fatal(err)
}
- encoded, err := EncodeBuf(x, nil)
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Logf("error during encode: %s", err)
+ t.Fatal(err)
+ }
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !casted.Equal(tm) {
return false
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ if !bytes.Equal(decoder.B, Junk) {
+ return false
+ }
+ decoder = NewDecoderFromBytes(append(encoded, Junk...), &DecodeOpts{
+ LeaveTAI: true,
+ })
+ decoded, err = decoder.Decode()
if err != nil {
- t.Logf("error during decode: %s", err)
+ t.Fatal(err)
+ }
+ casted, ok = decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ {
+ tai, isLeap := tai64n.Leapsecs.Sub(casted)
+ if isLeap {
+ return false
+ }
+ if !tai.Equal(tm) {
+ return false
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ return false
+ }
+ {
+ var encoded2 []byte
+ encoded2, err = EncodeBuf(casted, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if bytes.Equal(encoded, encoded2) {
+ return false
+ }
+ encoded2, err = EncodeBuf(casted, &EncodeOpts{LeaveTAI: true})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, encoded2) {
+ return false
+ }
+ }
+ }
+ decoder = NewDecoderFromBytes(append(encoded, Junk...), &DecodeOpts{
+ LeaveTAI64: true,
+ })
+ decoded, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ {
+ tai, ok := decoded.(*tai64n.TAI64)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(encoded[1:], tai[:]) {
+ return false
+ }
+ var raw []byte
+ raw, err = EncodeBuf(tai, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(raw, encoded) {
+ return false
+ }
+ }
+ return bytes.Equal(decoder.B, Junk)
+ }
+ if err := quick.Check(f, nil); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestTAINSymmetric(t *testing.T) {
+ f := func(secs int64, nsecs uint32) bool {
+ if (secs > (1<<62)-1) || (secs < -(1 << 62)) {
+ return true
+ }
+ nsecs %= 1000
+ if nsecs == 0 {
+ return true
+ }
+ tm := time.Unix(secs, int64(nsecs))
+ encoded, err := EncodeBuf(tm, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ casted, ok := decoded.(time.Time)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !casted.Equal(tm) {
+ return false
+ }
+ if !bytes.Equal(decoder.B, Junk) {
return false
}
- udecoded, ok := decoded.(time.Time)
+ decoder = NewDecoderFromBytes(append(encoded, Junk...), &DecodeOpts{
+ LeaveTAI: true,
+ })
+ decoded, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ casted, ok = decoded.(time.Time)
if !ok {
+ t.Fatal("failed to cast")
+ }
+ {
+ tai, isLeap := tai64n.Leapsecs.Sub(casted)
+ if isLeap {
+ return false
+ }
+ if !tai.Equal(tm) {
+ return false
+ }
+ if !bytes.Equal(decoder.B, Junk) {
+ return false
+ }
+ {
+ var encoded2 []byte
+ encoded2, err = EncodeBuf(casted, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if bytes.Equal(encoded, encoded2) {
+ return false
+ }
+ encoded2, err = EncodeBuf(casted, &EncodeOpts{LeaveTAI: true})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(encoded, encoded2) {
+ return false
+ }
+ }
+ }
+ decoder = NewDecoderFromBytes(append(encoded, Junk...), &DecodeOpts{
+ LeaveTAI64: true,
+ })
+ decoded, err = decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ {
+ tai, ok := decoded.(*tai64n.TAI64N)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(encoded[1:], tai[:]) {
+ return false
+ }
+ var raw []byte
+ raw, err = EncodeBuf(tai, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(raw, encoded) {
+ return false
+ }
+ }
+ return bytes.Equal(decoder.B, Junk)
+ }
+ if err := quick.Check(f, nil); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestTAINASymmetric(t *testing.T) {
+ f := func(secs int64, nsecs, asecs uint32) bool {
+ if (secs > (1<<62)-1) || (secs < -(1 << 62)) {
+ return true
+ }
+ nsecs %= 1000
+ asecs %= 1000
+ if asecs == 0 {
+ return true
+ }
+ secs += tai64n.Base
+ encoded := make([]byte, 1+tai64n.TAI64NASize)
+ encoded[0] = byte(AtomTAI64NA)
+ be.Put(encoded[1:1+8], uint64(secs))
+ be.Put(encoded[1+8:1+8+4], uint64(nsecs))
+ be.Put(encoded[1+8+4:1+8+4+4], uint64(asecs))
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
+ if err != nil {
+ t.Fatal(err)
+ }
+ casted, ok := decoded.(*tai64n.TAI64NA)
+ if !ok {
+ t.Fatal("failed to cast")
+ }
+ if !bytes.Equal(casted[:], encoded[1:]) {
return false
}
- return x.Equal(udecoded)
+ if !bytes.Equal(decoder.B, Junk) {
+ return false
+ }
+ {
+ var raw []byte
+ raw, err = EncodeBuf(casted, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(raw, encoded) {
+ return false
+ }
+ }
+ return true
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
// GoKEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
+// Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
import (
"bytes"
- "reflect"
+ "io"
"testing"
"testing/quick"
)
func TestUUIDEncodeDecode(t *testing.T) {
- object, _ := uuid.Parse("12345678-1234-5678-1234-567812345678")
- binstring := mustHexDec("0412345678123456781234567812345678")
- decoded, err := NewDecoderFromBytes(binstring, nil).Decode()
+ obj := uuid.MustParse("12345678-1234-5678-1234-567812345678")
+ bin := mustHexDec("0412345678123456781234567812345678")
+ decoder := NewDecoderFromBytes(append(bin, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during decode: %s", err)
+ t.Fatal(err)
}
- if err != nil {
- t.Fatalf("error during encode: %s", err)
+ casted, ok := decoded.(uuid.UUID)
+ if !ok {
+ t.Fatal("failed to cast")
}
- if decoded != object {
- t.Fatalf("expected %v, got %v", object, decoded)
+ if casted != obj {
+ t.Fatal("casted differs")
}
- encoded, err := EncodeBuf(object, nil)
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
+ }
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
+ t.Fatal(err)
}
- if !bytes.Equal(encoded, binstring) {
- t.Fatalf("expected %v, got %v", binstring, encoded)
+ if !bytes.Equal(encoded, bin) {
+ t.Fatal("encoded differs")
+ }
+}
+
+func TestUUIDNotEnoughData(t *testing.T) {
+ bin := mustHexDec("0412345678123456781234567812345678")
+ _, err := NewDecoderFromBytes(bin[:len(bin)-4], nil).Decode()
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal(err)
}
}
func TestUUIDSymmetric(t *testing.T) {
- f := func(object uuid.UUID) bool {
- encoded, err := EncodeBuf(object, nil)
+ f := func(obj uuid.UUID) bool {
+ encoded, err := EncodeBuf(obj, nil)
if err != nil {
- t.Fatalf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+ decoder := NewDecoderFromBytes(append(encoded, Junk...), nil)
+ decoded, err := decoder.Decode()
if err != nil {
- t.Fatalf("error during encode: %s", err)
- return false
+ t.Fatal(err)
}
- udecoded, ok := decoded.(uuid.UUID)
+ casted, ok := decoded.(uuid.UUID)
if !ok {
- t.Fatalf("failed to cast to uuid.UUID")
- return false
+ t.Fatal("failed to cast")
}
- if object != udecoded {
- t.Logf("expected <%s, %d>", reflect.TypeOf(object), object)
- t.Logf("instead <%s, %d>", reflect.TypeOf(udecoded), udecoded)
- return false
+ if !bytes.Equal(decoder.B, Junk) {
+ t.Fatal("tail differs")
}
- return true
+ return casted == obj
}
if err := quick.Check(f, nil); err != nil {
t.Fatal(err)
loads(bytes.fromhex("0C8301"))
self.assertEqual(err.exception.n, 2)
- def test_throws_when_unminimal_int(self) -> None:
+ def test_throws_when_nonminimal_int(self) -> None:
with self.assertRaises(DecodeError) as err:
encoded: bytes = bytes.fromhex("0C81007B")
loads(encoded)
self.assertEqual(str(err.exception), "map keys can not be empty")
def test_throws_when_decoding_empty_str_as_key(self):
- encoded = b"".join((
- bytes.fromhex("09"),
- bytes.fromhex("C0"),
- bytes.fromhex("0C8101"),
- bytes.fromhex("C4"), b"key1",
- bytes.fromhex("C6"), b"value1",
- bytes.fromhex("00"),
- ))
+ encoded = bytes.fromhex("09" + "C0" + "C0" + "00")
with self.assertRaises(DecodeError) as err:
decoded, tail = loads(encoded)
self.assertEqual(str(err.exception), "empty key")
self.assertSequenceEqual(decoded, s)
self.assertSequenceEqual(tail, junk)
- def test_throws_when_null_byte_in_utf(self) -> None:
+ def test_throws_when_null_byte_in_utf8(self) -> None:
with self.assertRaises(DecodeError) as err:
result, tail = loads(b"\xc5he\x00\x01\x02")
self.assertEqual(str(err.exception), "null byte in UTF-8")