From 8181d884b4bc6a69947281b05a97b5c086923ad1dd421bab298259d8f348ae3d Mon Sep 17 00:00:00 2001 From: RudenkoAD Date: Mon, 20 Jan 2025 11:32:15 +0300 Subject: [PATCH] add tests --- go/bin_test.go | 184 +++++++++++++ go/blob_test.go | 206 +++++++++++++++ go/bool_test.go | 52 ++++ go/float_test.go | 140 ++++++++++ go/generic_test.go | 33 +++ go/int_test.go | 641 +++++++++++++++++++++++++++++++++++++++++++++ go/list_test.go | 76 ++++++ go/map_test.go | 117 +++++++++ go/string_test.go | 256 ++++++++++++++++++ go/tai_test.go | 196 ++++++++++++++ go/uuid_test.go | 65 +++++ 11 files changed, 1966 insertions(+) create mode 100644 go/bin_test.go create mode 100644 go/blob_test.go create mode 100644 go/bool_test.go create mode 100644 go/float_test.go create mode 100644 go/generic_test.go create mode 100644 go/int_test.go create mode 100644 go/list_test.go create mode 100644 go/map_test.go create mode 100644 go/string_test.go create mode 100644 go/tai_test.go create mode 100644 go/uuid_test.go diff --git a/go/bin_test.go b/go/bin_test.go new file mode 100644 index 0000000..67b5f1f --- /dev/null +++ b/go/bin_test.go @@ -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 index 0000000..18a61de --- /dev/null +++ b/go/blob_test.go @@ -0,0 +1,206 @@ +// GoKEKS -- Go KEKS codec implementation +// Copyright (C) 2024-2025 Sergey Matveev +// +// 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 . + +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 index 0000000..0fa5389 --- /dev/null +++ b/go/bool_test.go @@ -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 index 0000000..fb82dd2 --- /dev/null +++ b/go/float_test.go @@ -0,0 +1,140 @@ +// GoKEKS -- Go KEKS codec implementation +// Copyright (C) 2024-2025 Sergey Matveev +// +// 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 . + +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 index 0000000..3b04b30 --- /dev/null +++ b/go/generic_test.go @@ -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 index 0000000..104fe7a --- /dev/null +++ b/go/int_test.go @@ -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 index 0000000..e375538 --- /dev/null +++ b/go/list_test.go @@ -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 index 0000000..724a35e --- /dev/null +++ b/go/map_test.go @@ -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 index 0000000..72a1803 --- /dev/null +++ b/go/string_test.go @@ -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 index 0000000..5cbec37 --- /dev/null +++ b/go/tai_test.go @@ -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 index 0000000..08d810f --- /dev/null +++ b/go/uuid_test.go @@ -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) + } +} -- 2.48.1