]> Cypherpunks repositories - keks.git/commitdiff
add tests
authorRudenkoAD <rudenko.ad@phystech.edu>
Mon, 20 Jan 2025 08:32:15 +0000 (11:32 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Mon, 10 Feb 2025 15:39:44 +0000 (18:39 +0300)
go/bin_test.go [new file with mode: 0644]
go/blob_test.go [new file with mode: 0644]
go/bool_test.go [new file with mode: 0644]
go/float_test.go [new file with mode: 0644]
go/generic_test.go [new file with mode: 0644]
go/int_test.go [new file with mode: 0644]
go/list_test.go [new file with mode: 0644]
go/map_test.go [new file with mode: 0644]
go/string_test.go [new file with mode: 0644]
go/tai_test.go [new file with mode: 0644]
go/uuid_test.go [new file with mode: 0644]

diff --git a/go/bin_test.go b/go/bin_test.go
new file mode 100644 (file)
index 0000000..67b5f1f
--- /dev/null
@@ -0,0 +1,184 @@
+package keks
+
+import (
+       "bytes"
+       "crypto/rand"
+       "encoding/hex"
+       "io"
+       "reflect"
+       "slices"
+       "strings"
+       "testing"
+       "testing/quick"
+)
+
+func TestBinaryEmpty(t *testing.T) {
+       object := []byte{}
+       hexstring := mustHexDec("80")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       if !bytes.Equal(decoded.([]byte), object) {
+               t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
+               t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
+               t.Error()
+       }
+}
+
+func TestBinary1234(t *testing.T) {
+       object := []byte{0x01, 0x02, 0x03, 0x04}
+       hexstring := mustHexDec("8401020304")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       if !bytes.Equal(decoded.([]byte), object) {
+               t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
+               t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
+               t.Error()
+       }
+}
+
+func TestBinaryLen62(t *testing.T) {
+       object := bytes.Repeat([]byte{'a'}, 62)
+       hexstring := mustHexDec("BD01" + strings.Repeat("61", 62))
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       if !bytes.Equal(decoded.([]byte), object) {
+               t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
+               t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
+               t.Error()
+       }
+}
+
+func TestBinaryLen318(t *testing.T) {
+       object := bytes.Repeat([]byte{'a'}, 318)
+       hexstring := mustHexDec("BE0001" + strings.Repeat("61", 318))
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       if !bytes.Equal(decoded.([]byte), object) {
+               t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
+               t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
+               t.Error()
+       }
+}
+
+func TestBinaryLen65853(t *testing.T) {
+       object := bytes.Repeat([]byte{'a'}, 65853)
+       hexstring := mustHexDec("BF0000000000000000" + strings.Repeat("61", 65853))
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       if !bytes.Equal(decoded.([]byte), object) {
+               t.Logf("expected type %s, value %s", reflect.TypeOf(object), object)
+               t.Logf("got type %s, value %s", reflect.TypeOf(decoded), decoded)
+               t.Error()
+       }
+}
+
+func TestBinaryThrowsWhenNotEnoughData(t *testing.T) {
+       hexstring := mustHexDec("84010203")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestBinaryThrowsWhenNotEnoughDataForLength8(t *testing.T) {
+       hexstring := mustHexDec("BD01" + strings.Repeat("61", 61))
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestBinaryThrowsWhenNotEnoughDataForLength16(t *testing.T) {
+       hexstring := mustHexDec("BE0001" + strings.Repeat("61", 317))
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestBinaryThrowsWhenNotEnoughDataForLength64(t *testing.T) {
+       hexstring := mustHexDec("BF0000000000000000" + strings.Repeat("61", 65852))
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestBinSymmetric(t *testing.T) {
+       f := func(x uint8) bool {
+               str := make([]byte, x)
+               rand.Read(str)
+               encoded, err := EncodeBuf(str, nil)
+               if err != nil {
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       return false
+               }
+               if !slices.Equal(str, decoded.([]byte)) {
+                       t.Logf("Expected <%s, %d>", reflect.TypeOf(str), str)
+                       t.Logf("Instead  <%s, %d>", reflect.TypeOf(decoded), decoded)
+                       return false
+               }
+               return true
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}
diff --git a/go/blob_test.go b/go/blob_test.go
new file mode 100644 (file)
index 0000000..18a61de
--- /dev/null
@@ -0,0 +1,206 @@
+// 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"
+       "encoding/hex"
+       "io"
+       "reflect"
+       "testing"
+       "testing/quick"
+)
+
+func TestMultipleOfChunkLen(t *testing.T) {
+       object := BlobChunked{
+               Chunks:   []string{"test", "data"},
+               ChunkLen: 4,
+       }
+       hexstring := mustHexDec("0B00000000000000038474657374846461746180")
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoder := NewDecoderFromBytes(encoded, nil)
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       udecoded, success := decoded.(BlobChunked)
+       if !success {
+               t.Errorf("failed to cast")
+       }
+       if object.ChunkLen != udecoded.ChunkLen {
+               t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+               t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+       }
+       for i := range len(object.Chunks) {
+               if object.Chunks[i] != udecoded.Chunks[i] {
+                       t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+                       t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+               }
+       }
+}
+
+func TestLargerOfChunkLen(t *testing.T) {
+       object := BlobChunked{
+               Chunks:   []string{"test", "data", "2"},
+               ChunkLen: 4,
+       }
+       hexstring := mustHexDec("0B0000000000000003847465737484646174618132")
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoder := NewDecoderFromBytes(encoded, nil)
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       udecoded, success := decoded.(BlobChunked)
+       if !success {
+               t.Errorf("failed to cast")
+       }
+       if object.ChunkLen != udecoded.ChunkLen {
+               t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+               t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+       }
+       for i := range len(object.Chunks) {
+               if object.Chunks[i] != udecoded.Chunks[i] {
+                       t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+                       t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+               }
+       }
+}
+
+func TestEmpty(t *testing.T) {
+       object := BlobChunked{
+               Chunks:   []string{},
+               ChunkLen: 4,
+       }
+       hexstring := mustHexDec("0B000000000000000380")
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoder := NewDecoderFromBytes(encoded, nil)
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       udecoded, success := decoded.(BlobChunked)
+       if !success {
+               t.Errorf("failed to cast")
+       }
+       if object.ChunkLen != udecoded.ChunkLen {
+               t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+               t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+       }
+       for i := range len(object.Chunks) {
+               if object.Chunks[i] != udecoded.Chunks[i] {
+                       t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+                       t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+               }
+       }
+}
+
+func TestBlobSymmetric(t *testing.T) {
+       f := func(ChunkLen uint8, ChunkNum uint8) bool {
+               if uint16(ChunkLen)*uint16(ChunkNum) > 2000 {
+                       return true
+               }
+               chunks := make([]string, ChunkNum)
+               for i := range ChunkNum {
+                       chunks[i] = RandStringBytes(int(ChunkLen))
+               }
+               object := BlobChunked{
+                       Chunks:   chunks,
+                       ChunkLen: int64(ChunkLen),
+               }
+               encoded, err := EncodeBuf(object, nil)
+               if err != nil {
+                       t.Errorf("error during encode: %s", err)
+                       return false
+               }
+               decoded, err := NewDecoderFromBytes(encoded, nil).Decode()
+               if err != nil {
+                       t.Errorf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(BlobChunked)
+               if !success {
+                       t.Errorf("failed to cast")
+                       return false
+               }
+               if object.ChunkLen != udecoded.ChunkLen {
+                       t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+                       t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+                       return false
+               }
+               for i := range len(object.Chunks) {
+                       if object.Chunks[i] != udecoded.Chunks[i] {
+                               t.Errorf("expected <%s, %v>", reflect.TypeOf(object), object)
+                               t.Errorf("instead  <%s, %v>", reflect.TypeOf(decoded), decoded)
+                               return false
+                       }
+               }
+               return true
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestBlobThrowsWhenNotEnoughData(t *testing.T) {
+       hexstring := mustHexDec("0B00000000000000038474657374846461")
+       _, err := NewDecoderFromBytes(hexstring, nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
+
+func TestBlobThrowsWhenNotEnoughDataForLength(t *testing.T) {
+       hexstring := mustHexDec("0B00000000")
+       _, err := NewDecoderFromBytes(hexstring, nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
+
+func TestBlobThrowsWhenWrongTerminatorLength(t *testing.T) {
+       hexstring := mustHexDec("0B0000000000000003847465737484646174618A7465726D696E61746F72")
+       _, err := NewDecoderFromBytes(hexstring, nil).Decode()
+       if err != ErrBlobBadChunkLen {
+               t.Errorf("expected ErrBlobBadChunkLen, got %s", err)
+       }
+}
+
+func TestBlobThrowsWhenWrongTerminatorTag(t *testing.T) {
+       hexstring := mustHexDec("0B00000000000000038474657374846461746104746861742077617320612077726F6E6720746167")
+       _, err := NewDecoderFromBytes(hexstring, nil).Decode()
+       if err != ErrBlobBadAtom {
+               t.Errorf("expected ErrBlobBadChunkLen, got %s", err)
+       }
+}
\ No newline at end of file
diff --git a/go/bool_test.go b/go/bool_test.go
new file mode 100644 (file)
index 0000000..0fa5389
--- /dev/null
@@ -0,0 +1,52 @@
+package keks
+
+import (
+       "bytes"
+       "encoding/hex"
+       "reflect"
+       "testing"
+)
+
+func TestTrue(t *testing.T) {
+       object := true
+       hexstring := mustHexDec("03")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestFalse(t *testing.T) {
+       object := false
+       hexstring := mustHexDec("02")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
diff --git a/go/float_test.go b/go/float_test.go
new file mode 100644 (file)
index 0000000..fb82dd2
--- /dev/null
@@ -0,0 +1,140 @@
+// 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"
+       "reflect"
+       "testing"
+)
+
+func TestThrowsWhenEncodingFloat(t *testing.T) {
+       _, err := EncodeBuf(1.5, nil)
+       if err == nil {
+               t.Errorf("expected Error, got nil")
+       }
+}
+
+func TestLoadsFloat16(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)...))
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       udecoded, success := decoded.(Raw)
+       if !success {
+               t.Errorf("expected Raw, got %v", reflect.TypeOf(decoded))
+       }
+       if !bytes.Equal(object, udecoded) {
+               t.Errorf("expected %v, got %v", object, decoded)
+       }
+}
+
+func TestLoadsFloat32(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)...))
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       udecoded, success := decoded.(Raw)
+       if !success {
+               t.Errorf("expected Raw, got %v", reflect.TypeOf(decoded))
+       }
+       if !bytes.Equal(object, udecoded) {
+               t.Errorf("expected %v, got %v", object, decoded)
+       }
+}
+
+func TestLoadsFloat64(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)...))
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       udecoded, success := decoded.(Raw)
+       if !success {
+               t.Errorf("expected Raw, got %v", reflect.TypeOf(decoded))
+       }
+       if !bytes.Equal(object, udecoded) {
+               t.Errorf("expected %v, got %v", object, decoded)
+       }
+}
+
+func TestLoadsFloat128(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)...))
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       udecoded, success := decoded.(Raw)
+       if !success {
+               t.Errorf("expected Raw, got %v", reflect.TypeOf(decoded))
+       }
+       if !bytes.Equal(object, udecoded) {
+               t.Errorf("expected %v, got %v", object, decoded)
+       }
+}
+
+func TestLoadsFloat256(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)...))
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       udecoded, success := decoded.(Raw)
+       if !success {
+               t.Errorf("expected Raw, got %v", reflect.TypeOf(decoded))
+       }
+       if !bytes.Equal(object, udecoded) {
+               t.Errorf("expected %v, got %v", object, decoded)
+       }
+}
+
+func TestThrowhsWhenNotEnoughDataForFloat256(t *testing.T) {
+       _, err := NewDecoderFromBytes(append([]byte{0x14}, bytes.Repeat([]byte{0x11}, 32-1)...), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
+
+func TestThrowhsWhenNotEnoughDataForFloat128(t *testing.T) {
+       _, err := NewDecoderFromBytes(append([]byte{0x13}, bytes.Repeat([]byte{0x11}, 16-1)...), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
+
+func TestThrowhsWhenNotEnoughDataForFloat64(t *testing.T) {
+       _, err := NewDecoderFromBytes(append([]byte{0x12}, bytes.Repeat([]byte{0x11}, 8-1)...), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
+
+func TestThrowhsWhenNotEnoughDataForFloat32(t *testing.T) {
+       _, err := NewDecoderFromBytes(append([]byte{0x11}, bytes.Repeat([]byte{0x11}, 4-1)...), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
+
+func TestThrowhsWhenNotEnoughDataForFloat16(t *testing.T) {
+       _, err := NewDecoderFromBytes(append([]byte{0x10}, bytes.Repeat([]byte{0x11}, 2-1)...), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %s", err)
+       }
+}
diff --git a/go/generic_test.go b/go/generic_test.go
new file mode 100644 (file)
index 0000000..3b04b30
--- /dev/null
@@ -0,0 +1,33 @@
+package keks
+
+import (
+       "io"
+       "testing"
+)
+
+func TestThrowsWhenUnknownTag(t *testing.T) {
+       hexstring := []byte{0x05}
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrUnknownType {
+               t.Errorf("expected ErrUnknownType, got %v", err)
+       }
+}
+
+func TestThrowsWhenEmptyData(t *testing.T) {
+       hexstring := []byte{}
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestLonelyEOC(t *testing.T) {
+       hexstring := []byte{0x00}
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrUnexpectedEOC {
+               t.Errorf("expected ErrUnexpectedEOC, got %v", err)
+       }
+}
\ No newline at end of file
diff --git a/go/int_test.go b/go/int_test.go
new file mode 100644 (file)
index 0000000..104fe7a
--- /dev/null
@@ -0,0 +1,641 @@
+package keks
+
+import (
+       "bytes"
+       "encoding/hex"
+       "io"
+       "math/big"
+       "reflect"
+       "testing"
+       "testing/quick"
+)
+
+func mustHexDec(s string) []byte {
+       b, err := hex.DecodeString(s)
+       if err != nil {
+               panic(err)
+       }
+       return b
+}
+
+func TestZero(t *testing.T) {
+       object := uint64(0)
+       hexstring := mustHexDec("0C80")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestOne(t *testing.T) {
+       object := uint64(1)
+       hexstring := mustHexDec("0C8101")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestNegativeOne(t *testing.T) {
+       object := int64(-1)
+       hexstring := mustHexDec("0D80")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func Test1s63(t *testing.T) {
+       object := big.NewInt(0).SetBytes(mustHexDec("800000000000000000"))
+       hexstring := mustHexDec("0C89800000000000000000")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func Test1s64(t *testing.T) {
+       object := big.NewInt(1).SetBytes(mustHexDec("010000000000000000"))
+       hexstring := mustHexDec("0C89010000000000000000")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func Test1s130(t *testing.T) {
+       object := big.NewInt(1).SetBytes(mustHexDec("0400000000000000000000000000000000"))
+       hexstring := mustHexDec("0C910400000000000000000000000000000000")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestM1s63(t *testing.T) {
+       object := big.NewInt(0).SetBytes(mustHexDec("00800000000000000000"))
+       object = object.Neg(object)
+       hexstring := mustHexDec("0D897FFFFFFFFFFFFFFFFF")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestM1s64(t *testing.T) {
+       object := big.NewInt(0).SetBytes(mustHexDec("010000000000000000"))
+       object = object.Neg(object)
+       hexstring := mustHexDec("0D88FFFFFFFFFFFFFFFF")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestM1s130(t *testing.T) {
+       object := big.NewInt(1).SetBytes(mustHexDec("0100000000000000000000000000000000"))
+       object = object.Neg(object)
+       hexstring := mustHexDec("0D90FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestDecodeNotEnoughData(t *testing.T) {
+       _, err := NewDecoderFromBytes(mustHexDec("0C830102"), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected error, got %v", err)
+       }
+       _, err = NewDecoderFromBytes(mustHexDec("0C8301"), nil).Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected error, got %v", err)
+       }
+}
+
+func TestThrowsWhenUnminimalInt(t *testing.T) {
+       encoded := mustHexDec("0C81007B")
+       _, err := NewDecoderFromBytes(encoded, nil).Decode()
+       if err != ErrIntNonMinimal {
+               t.Errorf("expected ErrIntNonMinimal, got %v", err)
+       }
+}
+
+func TestThrowsWhenNonBinInInt(t *testing.T) {
+       encoded := mustHexDec("0C017B")
+       _, err := NewDecoderFromBytes(encoded, nil).Decode()
+       if err != ErrBadInt {
+               t.Errorf("expected ErrBadInt, got %v", err)
+       }
+}
+func TestTemp(t *testing.T) {
+       object, suc := big.NewInt(1).SetString("-400000000000000000090009090909090909000000000000", 10)
+       t.Log(object)
+       if !suc {
+               t.Errorf("expected ErrBadInt, got %v", suc)
+       }
+}
+
+func TestUInt64Symmetric(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
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               if x != decoded {
+                       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.Error(err)
+       }
+}
+
+func TestUInt32Symmetric(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
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != uint32(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.Error(err)
+       }
+}
+func TestUInt16Symmetric(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
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != uint16(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.Error(err)
+       }
+}
+func TestUInt8Symmetric(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
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != uint8(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.Error(err)
+       }
+}
+
+func TestPlusInt32Symmetric(t *testing.T) {
+       f := func(x int32) bool {
+               if x == -1<<31 {
+                       return true
+               }
+               if x < 0 {
+                       x = -x
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int32(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.Error(err)
+       }
+}
+
+func TestMinusInt32Symmetric(t *testing.T) {
+       f := func(x int32) bool {
+               if x > 0 {
+                       x = -x
+               }
+               if x == 0 {
+                       return true
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(int64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int32(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.Error(err)
+       }
+}
+
+func TestPlusInt16Symmetric(t *testing.T) {
+       f := func(x int16) bool {
+               if x == -1<<15 {
+                       return true
+               }
+               if x < 0 {
+                       x = -x
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int16(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.Error(err)
+       }
+}
+
+func TestMinusInt16Symmetric(t *testing.T) {
+       f := func(x int16) bool {
+               if x > 0 {
+                       x = -x
+               }
+               if x == 0 {
+                       return true
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(int64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int16(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.Error(err)
+       }
+}
+
+func TestPlusInt8Symmetric(t *testing.T) {
+       f := func(x int8) bool {
+               if x == -1<<7 {
+                       return true
+               }
+               if x < 0 {
+                       x = -x
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int8(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.Error(err)
+       }
+}
+
+func TestMinusInt8Symmetric(t *testing.T) {
+       f := func(x int8) bool {
+               if x > 0 {
+                       x = -x
+               }
+               if x == 0 {
+                       return true
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(int64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int8(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.Error(err)
+       }
+}
+
+func TestPlusInt64Symmetric(t *testing.T) {
+       f := func(x int64) bool {
+               if x < 0 {
+                       x = -x
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(uint64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int64(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.Error(err)
+       }
+}
+
+func TestMinusInt64Symmetric(t *testing.T) {
+       f := func(x int64) bool {
+               if x > 0 {
+                       x = -x
+               }
+               if x == 0 {
+                       return true
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+
+               }
+               udecoded, success := decoded.(int64)
+               if !success {
+                       t.Logf("failed to cast")
+                       return false
+               }
+               if x != int64(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.Error(err)
+       }
+}
diff --git a/go/list_test.go b/go/list_test.go
new file mode 100644 (file)
index 0000000..e375538
--- /dev/null
@@ -0,0 +1,76 @@
+package keks
+
+import (
+       "bytes"
+       "encoding/hex"
+       "io"
+       "reflect"
+       "slices"
+       "testing"
+       "testing/quick"
+)
+
+func TestListEmpty(t *testing.T) {
+       object := []any{}
+       hexstring := []byte("\x08\x00")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       udecoded, success := decoded.([]any)
+       if !success {
+               t.Errorf("failed to cast")
+       }
+       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.Error()
+       }
+}
+
+func TestThrowsWhenNoEOC(t *testing.T) {
+       hexstring := []byte("\x08")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestListIntSymmetric(t *testing.T) {
+       f := func(x []uint64) bool {
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       return false
+               }
+               udecoded, success := decoded.([]any)
+               if !success {
+
+                       t.Errorf("failed to cast")
+               }
+               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)
+                               return false
+                       }
+               }
+               return true
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}
diff --git a/go/map_test.go b/go/map_test.go
new file mode 100644 (file)
index 0000000..724a35e
--- /dev/null
@@ -0,0 +1,117 @@
+package keks
+
+import (
+       "bytes"
+       "encoding/hex"
+       "maps"
+       "reflect"
+       "testing"
+       "testing/quick"
+)
+
+func TestEmptyMap(t *testing.T) {
+       hexstring := []byte("\x09\x00")
+       object := make(map[string]any)
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       udecoded, success := decoded.(map[string]any)
+       if !success {
+               t.Errorf("failed to cast")
+       }
+       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()
+       }
+}
+
+func TestThrowsWhenNonStringKey(t *testing.T) {
+       object := make(map[any]any)
+       object[1] = "a"
+       hexstring := []byte("\x09\x0C\x80\xC6value2\x00")
+       _, err := EncodeBuf(object, nil)
+       if err != ErrMapBadKey {
+               t.Errorf("expected ErrMapBadKey during encode, got %v", err)
+       }
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err = decoder.Decode()
+       if err != ErrMapBadKey {
+               t.Errorf("expected ErrMapBadKey during decode, got %v", err)
+       }
+}
+
+func TestThrowsWhenUnexpectedEOC(t *testing.T) {
+       hexstring := []byte("\x09\xC4key1\x00\x00")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrUnexpectedEOC {
+               t.Errorf("expected ErrUnexpectedEOC during decode, got %v", err)
+       }
+}
+
+func TestThrowsWhenEmptyStringKey(t *testing.T) {
+       object := make(map[any]any)
+       object[""] = "a"
+       hexstring := []byte("\x09\xC0\x0C\x81\x01\xC4key1\xC6value1\x00")
+       _, err := EncodeBuf(object, nil)
+       if err != ErrMapBadKey {
+               t.Errorf("expected ErrMapBadKey during encode, got %v", err)
+       }
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err = decoder.Decode()
+       if err != ErrMapBadKey {
+               t.Errorf("expected ErrMapBadKey during decode, got %v", err)
+       }
+}
+
+func TestThrowsWhenUnsortedKeys(t *testing.T) {
+       hexstring := []byte("\x09\xC4key2\xC6value2\xC4key1\xC6value1\x00")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrMapUnordered {
+               t.Errorf("expected ErrMapUnordered during decode, got %v", err)
+       }
+}
+
+func TestMapIntSymmetric(t *testing.T) {
+       f := func(x map[string]uint64) bool {
+               delete(x, "")
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(map[string]any)
+               if !success {
+                       t.Logf("failed to cast")
+                       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)
+                               return false
+                       }
+               }
+               return true
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}
diff --git a/go/string_test.go b/go/string_test.go
new file mode 100644 (file)
index 0000000..72a1803
--- /dev/null
@@ -0,0 +1,256 @@
+package keks
+
+import (
+       "bytes"
+       "encoding/hex"
+       "io"
+       "math/rand"
+       "reflect"
+       "strings"
+       "testing"
+       "testing/quick"
+)
+
+func TestEmptyString(t *testing.T) {
+       object := ""
+       hexstring := mustHexDec("C0")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestStringLen62(t *testing.T) {
+       object := strings.Repeat("a", 62)
+       hexstring := mustHexDec(
+               strings.Join([]string{"FD01", strings.Repeat("61", 62)}, ""),
+       )
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestStringLen318(t *testing.T) {
+       object := strings.Repeat("a", 318)
+       hexstring := mustHexDec(
+               strings.Join([]string{"FE0001", strings.Repeat("61", 318)}, ""),
+       )
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected hexstring %s, got %s", hex.EncodeToString(hexstring), hex.EncodeToString(encoded))
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestStringLen65853(t *testing.T) {
+       object := strings.Repeat("a", 65853)
+       hexstring := mustHexDec(
+               strings.Join([]string{"FF0000000000000000", strings.Repeat("61", 65853)}, ""),
+       )
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       encoded, err := EncodeBuf(object, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if !bytes.Equal(encoded, hexstring) {
+               t.Logf("expected hexstring to begin with %s, got %s", hex.EncodeToString(hexstring)[:40], hex.EncodeToString(encoded)[:40])
+               t.Fail()
+       }
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %s", err)
+       }
+       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.Error()
+       }
+}
+
+func TestThrowsWhenNullByteInUTF8(t *testing.T) {
+       hexstring := []byte("\xC5he\x00\x01\x02")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrBadUTF8 {
+               t.Errorf("expected ErrBadUTF8, got %v", err)
+       }
+}
+
+func TestOkWhenNullByteInUTF8AndUTF8CheckDisabled(t *testing.T) {
+       hexstring := []byte("\xC5he\xe2\x82\x28")
+       decoder := NewDecoderFromBytes(hexstring, &DecodeOpts{DisableUTF8Check: true})
+       _, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+}
+
+func TestThrowsWhenInvalid2BytesInUTF8(t *testing.T) {
+       hexstring := []byte("\xC5he\xc3\x28o")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrBadUTF8 {
+               t.Errorf("expected ErrBadUTF8, got %v", err)
+       }
+}
+
+func TestOkWhenInvalid2BytesUTF8AndUTF8CheckDisabled(t *testing.T) {
+       hexstring := []byte("\xC5he\xc3\x28o")
+       decoder := NewDecoderFromBytes(hexstring, &DecodeOpts{DisableUTF8Check: true})
+       _, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+}
+
+func TestThrowsWhenInvalidUTF3Bytes(t *testing.T) {
+       hexstring := []byte("\xC5he\xe2\x82\x28")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != ErrBadUTF8 {
+               t.Errorf("expected ErrBadUTF8, got %v", err)
+       }
+}
+
+func TestOkWhenInvalid3BytesUTF8AndUTF8CheckDisabled(t *testing.T) {
+       hexstring := []byte("\xC5he\xe2\x82\x28")
+       decoder := NewDecoderFromBytes(hexstring, &DecodeOpts{DisableUTF8Check: true})
+       _, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+}
+
+func TestThrowsWhenNotEnoughData(t *testing.T) {
+       hexstring := []byte("\xC5he")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestThrowsWhenNotEnoughDataForLength8(t *testing.T) {
+       hexstring := []byte("\xC5he")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestThrowsWhenNotEnoughDataForLength16(t *testing.T) {
+       hexstring := []byte("\xC5he")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+func TestThrowsWhenNotEnoughDataForLength64(t *testing.T) {
+       hexstring := []byte("\xC5he")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != io.ErrUnexpectedEOF {
+               t.Errorf("expected io.ErrUnexpectedEOF, got %v", err)
+       }
+}
+
+const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+func RandStringBytes(n int) string {
+       b := make([]byte, n)
+       for i := range b {
+               b[i] = letterBytes[rand.Intn(len(letterBytes))]
+       }
+       return string(b)
+}
+
+func TestThrowsWhenStringTooLong(t *testing.T) {
+       f := func(x uint8, y uint8) bool {
+               if (y == x) || (y == 0) || (x == 0) {
+                       return true
+               }
+               if y > x {
+                       z := x
+                       x = y
+                       y = z
+               }
+               str := RandStringBytes(int(x))
+               encoded, _ := EncodeBuf(str, nil)
+               decoder := NewDecoderFromBytes(encoded, &DecodeOpts{MaxStrLen: int64(x - 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.Error(err)
+       }
+}
+
+func TestStringSymmetric(t *testing.T) {
+       f := func(x uint8) bool {
+               str := RandStringBytes(int(x))
+               encoded, err := EncodeBuf(str, nil)
+               if err != nil {
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               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.Error(err)
+       }
+}
diff --git a/go/tai_test.go b/go/tai_test.go
new file mode 100644 (file)
index 0000000..5cbec37
--- /dev/null
@@ -0,0 +1,196 @@
+package keks
+
+import (
+       "bytes"
+       "testing"
+       "testing/quick"
+       "time"
+)
+
+func TestLargeNumberOfSeconds(t *testing.T) {
+       hexstring := mustHexDec("187000000065195F65")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       t.Log(decoded)
+}
+
+func TestThrowsWhenMsbIsSet(t *testing.T) {
+       hexstring := mustHexDec("188000000065195F65")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err == nil {
+               t.Errorf("expected 'reserved TAI64 value is in use', got %v", err)
+       }
+}
+
+func TestThrowsWhenTooManyNanosecs(t *testing.T) {
+       hexstring := bytes.Join([][]byte{mustHexDec("194000000065195F65"), []byte(";\x9a\xca\x00")}, nil)
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err == nil {
+               t.Errorf("expected 'too many nanoseconds', got %v", err)
+       }
+}
+
+func TestThrowsWhenZeroNanoseconds(t *testing.T) {
+       hexstring := mustHexDec("19400000000000000000000000")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err == nil {
+               t.Errorf("expected 'non-minimal TAI64N', got %v", err)
+       }
+}
+
+func TestThrowsWhenTooManyAttoseconds(t *testing.T) {
+       hexstring := mustHexDec("1A4000000065195F65075BCA00A75BCA00")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err == nil {
+               t.Errorf("expected 'too many attoseconds', got %v", err)
+       }
+}
+
+func TestThrowsWhenZeroAttoseconds(t *testing.T) {
+       hexstring := mustHexDec("1A40000000000000000000000000000000")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err == nil {
+               t.Errorf("expected 'non-minimal TAI64NA', got %v", err)
+       }
+}
+
+func TestZeroNanosecondsOkForTAI64NA(t *testing.T) {
+       hexstring := mustHexDec("1A40000000000000000000000000000001")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("expected no error, got %v", err)
+       }
+}
+
+func TestThrowsWhenMsbIsSetForTAI64NA(t *testing.T) {
+       hexstring := bytes.Join([][]byte{mustHexDec("1A8000000065195F65"), mustHexDec("00010000"), mustHexDec("00010000")}, nil)
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       _, err := decoder.Decode()
+       if err == nil {
+               t.Errorf("expected 'reserved TAI64 value is in use', got %v", err)
+       }
+}
+
+func Test19700101(t *testing.T) {
+       hexstring := mustHexDec("18400000000000000A")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       expected := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)
+       decodedTime := decoded.(time.Time)
+       if !decodedTime.Equal(expected) {
+               t.Errorf("expected %v, got %v", expected, decoded)
+       }
+}
+
+func Test19920602(t *testing.T) {
+       hexstring := mustHexDec("18400000002A2B2C2D")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       decodedTime := decoded.(time.Time)
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       expected := time.Date(1992, 6, 2, 8, 6, 43, 0, time.UTC)
+       if !decodedTime.Equal(expected) {
+               t.Errorf("expected %v, got %v", expected, decoded)
+       }
+}
+
+func Test19971003(t *testing.T) {
+       hexstring := mustHexDec("184000000034353637")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       decodedTime := decoded.(time.Time)
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       expected := time.Date(1997, 10, 3, 18, 14, 48, 0, time.UTC)
+       if !decodedTime.Equal(expected) {
+               t.Errorf("expected %v, got %v", expected, decoded)
+       }
+}
+
+func Test20161231(t *testing.T) {
+       hexstring := mustHexDec("1840000000586846A3")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       decodedTime := decoded.(time.Time)
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       expected := time.Date(2016, 12, 31, 23, 59, 59, 0, time.UTC)
+       if !decodedTime.Equal(expected) {
+               t.Errorf("expected %v, got %v", expected, decoded)
+       }
+}
+
+func Test20170101(t *testing.T) {
+       hexstring := mustHexDec("1840000000586846A5")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       decodedTime := decoded.(time.Time)
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       expected := time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC)
+       if !decodedTime.Equal(expected) {
+               t.Errorf("expected %v, got %v", expected, decoded)
+       }
+}
+
+func Test20241120(t *testing.T) {
+       hexstring := mustHexDec("1940000000673DD3E136F11FE0")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       decodedTime := decoded.(time.Time)
+       if err != nil {
+               t.Errorf("error during decode: %v", err)
+       }
+       expected := time.Date(2024, 11, 20, 12, 19, 8, 921772000, time.UTC)
+       if !decodedTime.Equal(expected) {
+               t.Errorf("expected %v, got %v", expected, decoded)
+       }
+}
+
+func TestTaiSymmetric(t *testing.T) {
+       f := func(a int64, b int64) bool {
+               x := time.Unix(a, b)
+               if a > 1<<62-1 {
+                       return true
+               }
+               if a < -1<<62 {
+                       return true
+               }
+               encoded, err := EncodeBuf(x, nil)
+               if err != nil {
+                       t.Logf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Logf("error during decode: %s", err)
+                       return false
+               }
+               udecoded, success := decoded.(time.Time)
+               if !success {
+                       return false
+               }
+               return x.Equal(udecoded)
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}
diff --git a/go/uuid_test.go b/go/uuid_test.go
new file mode 100644 (file)
index 0000000..08d810f
--- /dev/null
@@ -0,0 +1,65 @@
+package keks
+
+import (
+       "bytes"
+       "reflect"
+       "testing"
+       "testing/quick"
+
+       "github.com/google/uuid"
+)
+
+func TestUUIDEncodeDecode(t *testing.T) {
+       object, _ := uuid.Parse("12345678-1234-5678-1234-567812345678")
+       hexstring := mustHexDec("0412345678123456781234567812345678")
+       decoder := NewDecoderFromBytes(hexstring, nil)
+       decoded, err := decoder.Decode()
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if decoded != object {
+               t.Errorf("expected %v, got %v", object, decoded)
+       }
+       encoded, err := EncodeBuf(hexstring, nil)
+       if err != nil {
+               t.Errorf("error during encode: %s", err)
+       }
+       if bytes.Equal(encoded, hexstring) {
+               t.Errorf("expected %v, got %v", hexstring, encoded)
+       }
+}
+
+func TestUUIDSymmetric(t *testing.T) {
+       f := func(x uuid.UUID) bool {
+               encoded, err := EncodeBuf(x[:], nil)
+               if err != nil {
+                       t.Errorf("error during encode: %s", err)
+                       return false
+               }
+               decoder := NewDecoderFromBytes(encoded, nil)
+               decoded, err := decoder.Decode()
+               if err != nil {
+                       t.Errorf("error during encode: %s", err)
+                       return false
+               }
+               decodedBytes, success := decoded.([]byte)
+               if !success {
+                       t.Errorf("failed to cast to []byte")
+                       return false
+               }
+               udecoded, err := uuid.FromBytes(decodedBytes)
+               if err != nil {
+                       t.Errorf("failed to cast to uuid")
+                       return false
+               }
+               if x != udecoded {
+                       t.Logf("expected <%s, %d>", reflect.TypeOf(x), x)
+                       t.Logf("instead  <%s, %d>", reflect.TypeOf(udecoded), udecoded)
+                       return false
+               }
+               return true
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}