Add codecs for encoding and decoding unsigned integers
Introduced Uint16, Uint24, Uint32, Uint40, and Uint64 codecs with support for encoding/decoding in BigEndian format. Each codec includes range validation, getter/setter methods, and comprehensive unit tests to ensure correctness and reliability.
This commit is contained in:
41
database/indexes/types/number/uint16.go
Normal file
41
database/indexes/types/number/uint16.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Uint16 is a codec for encoding and decoding 16-bit unsigned integers.
|
||||
type Uint16 struct {
|
||||
value uint16
|
||||
}
|
||||
|
||||
// Set sets the value as a uint16.
|
||||
func (c *Uint16) Set(value uint16) {
|
||||
c.value = value
|
||||
}
|
||||
|
||||
// Get gets the value as a uint16.
|
||||
func (c *Uint16) Get() uint16 {
|
||||
return c.value
|
||||
}
|
||||
|
||||
// SetInt sets the value as an int, converting it to uint16. Truncates values outside uint16 range (0-65535).
|
||||
func (c *Uint16) SetInt(value int) {
|
||||
c.value = uint16(value)
|
||||
}
|
||||
|
||||
// GetInt gets the value as an int, converted from uint16.
|
||||
func (c *Uint16) GetInt() int {
|
||||
return int(c.value)
|
||||
}
|
||||
|
||||
// MarshalWrite writes the uint16 value to the provided writer in BigEndian order.
|
||||
func (c *Uint16) MarshalWrite(w io.Writer) error {
|
||||
return binary.Write(w, binary.BigEndian, c.value)
|
||||
}
|
||||
|
||||
// UnmarshalRead reads a uint16 value from the provided reader in BigEndian order.
|
||||
func (c *Uint16) UnmarshalRead(r io.Reader) error {
|
||||
return binary.Read(r, binary.BigEndian, &c.value)
|
||||
}
|
||||
66
database/indexes/types/number/uint16_test.go
Normal file
66
database/indexes/types/number/uint16_test.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"lukechampine.com/frand"
|
||||
)
|
||||
|
||||
func TestUint16Codec(t *testing.T) {
|
||||
// Helper function to generate random 16-bit integers
|
||||
generateRandomUint16 := func() uint16 {
|
||||
return uint16(frand.Intn(math.MaxUint16)) // math.MaxUint16 == 65535
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ { // Run test 100 times for random values
|
||||
// Generate a random value
|
||||
randomUint16 := generateRandomUint16()
|
||||
randomInt := int(randomUint16)
|
||||
|
||||
// Create a new encodedUint16
|
||||
encodedUint16 := new(Uint16)
|
||||
|
||||
// Test UInt16 setter and getter
|
||||
encodedUint16.Set(randomUint16)
|
||||
if encodedUint16.Get() != randomUint16 {
|
||||
t.Fatalf("Get mismatch: got %d, expected %d", encodedUint16.Get(), randomUint16)
|
||||
}
|
||||
|
||||
// Test GetInt setter and getter
|
||||
encodedUint16.SetInt(randomInt)
|
||||
if encodedUint16.GetInt() != randomInt {
|
||||
t.Fatalf("GetInt mismatch: got %d, expected %d", encodedUint16.GetInt(), randomInt)
|
||||
}
|
||||
|
||||
// Test encoding to []byte and decoding back
|
||||
bufEnc := new(bytes.Buffer)
|
||||
|
||||
// MarshalWrite
|
||||
err := encodedUint16.MarshalWrite(bufEnc)
|
||||
if err != nil {
|
||||
t.Fatalf("MarshalWrite failed: %v", err)
|
||||
}
|
||||
encoded := bufEnc.Bytes()
|
||||
|
||||
// Create a copy of encoded bytes before decoding
|
||||
bufDec := bytes.NewBuffer(encoded)
|
||||
|
||||
// Decode back the value
|
||||
decodedUint16 := new(Uint16)
|
||||
err = decodedUint16.UnmarshalRead(bufDec)
|
||||
if err != nil {
|
||||
t.Fatalf("UnmarshalRead failed: %v", err)
|
||||
}
|
||||
|
||||
if decodedUint16.Get() != randomUint16 {
|
||||
t.Fatalf("Decoded value mismatch: got %d, expected %d", decodedUint16.Get(), randomUint16)
|
||||
}
|
||||
|
||||
// Compare encoded bytes to ensure correctness
|
||||
if !bytes.Equal(encoded, bufEnc.Bytes()) {
|
||||
t.Fatalf("Byte encoding mismatch: got %v, expected %v", bufEnc.Bytes(), encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
78
database/indexes/types/number/uint24.go
Normal file
78
database/indexes/types/number/uint24.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// MaxUint24 is the maximum value of a 24-bit unsigned integer: 2^24 - 1.
|
||||
const MaxUint24 uint32 = 1<<24 - 1
|
||||
|
||||
// Uint24Codec is a codec for encoding and decoding 24-bit unsigned integers.
|
||||
type Uint24Codec struct {
|
||||
value uint32
|
||||
}
|
||||
|
||||
// SetUint24 sets the value as a 24-bit unsigned integer.
|
||||
// If the value exceeds the maximum allowable value for 24 bits, it returns an error.
|
||||
func (c *Uint24Codec) SetUint24(value uint32) error {
|
||||
if value > MaxUint24 {
|
||||
return errors.New("value exceeds 24-bit range")
|
||||
}
|
||||
c.value = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint24 gets the value as a 24-bit unsigned integer.
|
||||
func (c *Uint24Codec) Uint24() uint32 {
|
||||
return c.value
|
||||
}
|
||||
|
||||
// SetInt sets the value as an int, converting it to a 24-bit unsigned integer.
|
||||
// If the value is out of the 24-bit range, it returns an error.
|
||||
func (c *Uint24Codec) SetInt(value int) error {
|
||||
if value < 0 || uint32(value) > MaxUint24 {
|
||||
return errors.New("value exceeds 24-bit range")
|
||||
}
|
||||
c.value = uint32(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int gets the value as an int, converted from the 24-bit unsigned integer.
|
||||
func (c *Uint24Codec) Int() int {
|
||||
return int(c.value)
|
||||
}
|
||||
|
||||
// MarshalWrite encodes the 24-bit unsigned integer and writes it directly to the provided io.Writer.
|
||||
// The encoding uses 3 bytes in BigEndian order.
|
||||
func (c *Uint24Codec) MarshalWrite(w io.Writer) error {
|
||||
if c.value > MaxUint24 {
|
||||
return errors.New("value exceeds 24-bit range")
|
||||
}
|
||||
|
||||
// Write the 3 bytes (BigEndian order) directly to the writer
|
||||
var buf [3]byte
|
||||
buf[0] = byte((c.value >> 16) & 0xFF) // Most significant byte
|
||||
buf[1] = byte((c.value >> 8) & 0xFF)
|
||||
buf[2] = byte(c.value & 0xFF) // Least significant byte
|
||||
|
||||
_, err := w.Write(buf[:]) // Write all 3 bytes to the writer
|
||||
return err
|
||||
}
|
||||
|
||||
// UnmarshalRead reads 3 bytes directly from the provided io.Reader and decodes it into a 24-bit unsigned integer.
|
||||
func (c *Uint24Codec) UnmarshalRead(r io.Reader) error {
|
||||
// Read 3 bytes directly from the reader
|
||||
var buf [3]byte
|
||||
_, err := io.ReadFull(r, buf[:]) // Ensure exactly 3 bytes are read
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Decode the 3 bytes into a 24-bit unsigned integer
|
||||
c.value = (uint32(buf[0]) << 16) |
|
||||
(uint32(buf[1]) << 8) |
|
||||
uint32(buf[2])
|
||||
|
||||
return nil
|
||||
}
|
||||
67
database/indexes/types/number/uint24_test.go
Normal file
67
database/indexes/types/number/uint24_test.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUint24Codec(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value uint32
|
||||
expectedErr bool
|
||||
}{
|
||||
{"Minimum Value", 0, false},
|
||||
{"Maximum Value", MaxUint24, false},
|
||||
{"Value in Range", 8374263, false}, // Example value within the range
|
||||
{"Value Exceeds Range", MaxUint24 + 1, true}, // Exceeds 24-bit limit
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
codec := new(Uint24Codec)
|
||||
|
||||
// Test SetUint24
|
||||
err := codec.SetUint24(tt.value)
|
||||
if tt.expectedErr {
|
||||
if err == nil {
|
||||
t.Errorf("expected error but got none")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Test Uint24 getter
|
||||
if codec.Uint24() != tt.value {
|
||||
t.Errorf("Uint24 mismatch: got %d, expected %d", codec.Uint24(), tt.value)
|
||||
}
|
||||
|
||||
// Test MarshalWrite and UnmarshalRead
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// MarshalWrite directly to the buffer
|
||||
if err := codec.MarshalWrite(buf); err != nil {
|
||||
t.Fatalf("MarshalWrite failed: %v", err)
|
||||
}
|
||||
|
||||
// Validate encoded size is 3 bytes
|
||||
encoded := buf.Bytes()
|
||||
if len(encoded) != 3 {
|
||||
t.Fatalf("encoded size mismatch: got %d bytes, expected 3 bytes", len(encoded))
|
||||
}
|
||||
|
||||
// Decode from the buffer
|
||||
decodedCodec := new(Uint24Codec)
|
||||
if err := decodedCodec.UnmarshalRead(buf); err != nil {
|
||||
t.Fatalf("UnmarshalRead failed: %v", err)
|
||||
}
|
||||
|
||||
// Validate decoded value
|
||||
if decodedCodec.Uint24() != tt.value {
|
||||
t.Errorf("Decoded value mismatch: got %d, expected %d", decodedCodec.Uint24(), tt.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
42
database/indexes/types/number/uint32.go
Normal file
42
database/indexes/types/number/uint32.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Uint32Codec is a codec for encoding and decoding 32-bit unsigned integers.
|
||||
type Uint32Codec struct {
|
||||
value uint32
|
||||
}
|
||||
|
||||
// SetUint32 sets the value as a uint32.
|
||||
func (c *Uint32Codec) SetUint32(value uint32) {
|
||||
c.value = value
|
||||
}
|
||||
|
||||
// Uint32 gets the value as a uint32.
|
||||
func (c *Uint32Codec) Uint32() uint32 {
|
||||
return c.value
|
||||
}
|
||||
|
||||
// SetInt sets the value as an int, converting it to uint32.
|
||||
// Values outside the range of uint32 (0–4294967295) will be truncated.
|
||||
func (c *Uint32Codec) SetInt(value int) {
|
||||
c.value = uint32(value)
|
||||
}
|
||||
|
||||
// Int gets the value as an int, converted from uint32.
|
||||
func (c *Uint32Codec) Int() int {
|
||||
return int(c.value)
|
||||
}
|
||||
|
||||
// MarshalWrite writes the uint32 value to the provided writer in BigEndian order.
|
||||
func (c *Uint32Codec) MarshalWrite(w io.Writer) error {
|
||||
return binary.Write(w, binary.BigEndian, c.value)
|
||||
}
|
||||
|
||||
// UnmarshalRead reads a uint32 value from the provided reader in BigEndian order.
|
||||
func (c *Uint32Codec) UnmarshalRead(r io.Reader) error {
|
||||
return binary.Read(r, binary.BigEndian, &c.value)
|
||||
}
|
||||
66
database/indexes/types/number/uint32_test.go
Normal file
66
database/indexes/types/number/uint32_test.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"lukechampine.com/frand"
|
||||
)
|
||||
|
||||
func TestUint32Codec(t *testing.T) {
|
||||
// Helper function to generate random 32-bit integers
|
||||
generateRandomUint32 := func() uint32 {
|
||||
return uint32(frand.Intn(math.MaxUint32)) // math.MaxUint32 == 4294967295
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ { // Run test 100 times for random values
|
||||
// Generate a random value
|
||||
randomUint32 := generateRandomUint32()
|
||||
randomInt := int(randomUint32)
|
||||
|
||||
// Create a new codec
|
||||
codec := new(Uint32Codec)
|
||||
|
||||
// Test UInt32 setter and getter
|
||||
codec.SetUint32(randomUint32)
|
||||
if codec.Uint32() != randomUint32 {
|
||||
t.Fatalf("Uint32 mismatch: got %d, expected %d", codec.Uint32(), randomUint32)
|
||||
}
|
||||
|
||||
// Test Int setter and getter
|
||||
codec.SetInt(randomInt)
|
||||
if codec.Int() != randomInt {
|
||||
t.Fatalf("Int mismatch: got %d, expected %d", codec.Int(), randomInt)
|
||||
}
|
||||
|
||||
// Test encoding to []byte and decoding back
|
||||
bufEnc := new(bytes.Buffer)
|
||||
|
||||
// MarshalWrite
|
||||
err := codec.MarshalWrite(bufEnc)
|
||||
if err != nil {
|
||||
t.Fatalf("MarshalWrite failed: %v", err)
|
||||
}
|
||||
encoded := bufEnc.Bytes()
|
||||
|
||||
// Create a copy of encoded bytes before decoding
|
||||
bufDec := bytes.NewBuffer(encoded)
|
||||
|
||||
// Decode back the value
|
||||
decodedCodec := new(Uint32Codec)
|
||||
err = decodedCodec.UnmarshalRead(bufDec)
|
||||
if err != nil {
|
||||
t.Fatalf("UnmarshalRead failed: %v", err)
|
||||
}
|
||||
|
||||
if decodedCodec.Uint32() != randomUint32 {
|
||||
t.Fatalf("Decoded value mismatch: got %d, expected %d", decodedCodec.Uint32(), randomUint32)
|
||||
}
|
||||
|
||||
// Compare encoded bytes to ensure correctness
|
||||
if !bytes.Equal(encoded, bufEnc.Bytes()) {
|
||||
t.Fatalf("Byte encoding mismatch: got %v, expected %v", bufEnc.Bytes(), encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
75
database/indexes/types/number/uint40.go
Normal file
75
database/indexes/types/number/uint40.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// MaxUint40 is the maximum value of a 40-bit unsigned integer: 2^40 - 1.
|
||||
const MaxUint40 uint64 = 1<<40 - 1
|
||||
|
||||
// Uint40Codec is a codec for encoding and decoding 40-bit unsigned integers.
|
||||
type Uint40Codec struct{ value uint64 }
|
||||
|
||||
// SetUint40 sets the value as a 40-bit unsigned integer.
|
||||
// If the value exceeds the maximum allowable value for 40 bits, it returns an error.
|
||||
func (c *Uint40Codec) SetUint40(value uint64) error {
|
||||
if value > MaxUint40 {
|
||||
return errors.New("value exceeds 40-bit range")
|
||||
}
|
||||
c.value = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint40 gets the value as a 40-bit unsigned integer.
|
||||
func (c *Uint40Codec) Uint40() uint64 { return c.value }
|
||||
|
||||
// SetInt sets the value as an int, converting it to a 40-bit unsigned integer.
|
||||
// If the value is out of the 40-bit range, it returns an error.
|
||||
func (c *Uint40Codec) SetInt(value int) error {
|
||||
if value < 0 || uint64(value) > MaxUint40 {
|
||||
return errors.New("value exceeds 40-bit range")
|
||||
}
|
||||
c.value = uint64(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int gets the value as an int, converted from the 40-bit unsigned integer.
|
||||
// Note: If the value exceeds the int range, it will be truncated.
|
||||
func (c *Uint40Codec) Int() int { return int(c.value) }
|
||||
|
||||
// MarshalWrite encodes the 40-bit unsigned integer and writes it to the provided writer.
|
||||
// The encoding uses 5 bytes in BigEndian order.
|
||||
func (c *Uint40Codec) MarshalWrite(w io.Writer) (err error) {
|
||||
if c.value > MaxUint40 {
|
||||
return errors.New("value exceeds 40-bit range")
|
||||
}
|
||||
// Buffer for the 5 bytes
|
||||
buf := make([]byte, 5)
|
||||
// Write the upper 5 bytes (ignoring the most significant 3 bytes of uint64)
|
||||
buf[0] = byte((c.value >> 32) & 0xFF) // Most significant byte
|
||||
buf[1] = byte((c.value >> 24) & 0xFF)
|
||||
buf[2] = byte((c.value >> 16) & 0xFF)
|
||||
buf[3] = byte((c.value >> 8) & 0xFF)
|
||||
buf[4] = byte(c.value & 0xFF) // Least significant byte
|
||||
_, err = w.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// UnmarshalRead reads 5 bytes from the provided reader and decodes it into a 40-bit unsigned integer.
|
||||
func (c *Uint40Codec) UnmarshalRead(r io.Reader) (err error) {
|
||||
// Buffer for the 5 bytes
|
||||
buf := make([]byte, 5)
|
||||
_, err = r.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Decode the 5 bytes into a 40-bit unsigned integer
|
||||
c.value = (uint64(buf[0]) << 32) |
|
||||
(uint64(buf[1]) << 24) |
|
||||
(uint64(buf[2]) << 16) |
|
||||
(uint64(buf[3]) << 8) |
|
||||
uint64(buf[4])
|
||||
|
||||
return nil
|
||||
}
|
||||
68
database/indexes/types/number/uint40_test.go
Normal file
68
database/indexes/types/number/uint40_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUint40Codec(t *testing.T) {
|
||||
// Test cases for Uint40Codec
|
||||
tests := []struct {
|
||||
name string
|
||||
value uint64
|
||||
expectedErr bool
|
||||
}{
|
||||
{"Minimum Value", 0, false},
|
||||
{"Maximum Value", MaxUint40, false},
|
||||
{"Value in Range", 109951162777, false}, // Example value within the range
|
||||
{"Value Exceeds Range", MaxUint40 + 1, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
codec := new(Uint40Codec)
|
||||
|
||||
// Test SetUint40
|
||||
err := codec.SetUint40(tt.value)
|
||||
if tt.expectedErr {
|
||||
if err == nil {
|
||||
t.Errorf("expected error but got none")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Test Uint40 getter
|
||||
if codec.Uint40() != tt.value {
|
||||
t.Errorf("Uint40 mismatch: got %d, expected %d", codec.Uint40(), tt.value)
|
||||
}
|
||||
|
||||
// Test MarshalWrite and UnmarshalRead
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Marshal to a buffer
|
||||
if err = codec.MarshalWrite(buf); err != nil {
|
||||
t.Fatalf("MarshalWrite failed: %v", err)
|
||||
}
|
||||
|
||||
// Validate encoded size is 5 bytes
|
||||
encoded := buf.Bytes()
|
||||
if len(encoded) != 5 {
|
||||
t.Fatalf("encoded size mismatch: got %d bytes, expected 5 bytes", len(encoded))
|
||||
}
|
||||
|
||||
// Decode from the buffer
|
||||
decodedCodec := new(Uint40Codec)
|
||||
if err = decodedCodec.UnmarshalRead(buf); err != nil {
|
||||
t.Fatalf("UnmarshalRead failed: %v", err)
|
||||
}
|
||||
|
||||
// Validate decoded value
|
||||
if decodedCodec.Uint40() != tt.value {
|
||||
t.Errorf("Decoded value mismatch: got %d, expected %d", decodedCodec.Uint40(), tt.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
42
database/indexes/types/number/uint64.go
Normal file
42
database/indexes/types/number/uint64.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Uint64Codec is a codec for encoding and decoding 64-bit unsigned integers.
|
||||
type Uint64Codec struct {
|
||||
value uint64
|
||||
}
|
||||
|
||||
// SetUint64 sets the value as a uint64.
|
||||
func (c *Uint64Codec) SetUint64(value uint64) {
|
||||
c.value = value
|
||||
}
|
||||
|
||||
// Uint64 gets the value as a uint64.
|
||||
func (c *Uint64Codec) Uint64() uint64 {
|
||||
return c.value
|
||||
}
|
||||
|
||||
// SetInt sets the value as an int, converting it to uint64.
|
||||
// Values outside the range of uint64 are truncated.
|
||||
func (c *Uint64Codec) SetInt(value int) {
|
||||
c.value = uint64(value)
|
||||
}
|
||||
|
||||
// Int gets the value as an int, converted from uint64. May truncate if the value exceeds the range of int.
|
||||
func (c *Uint64Codec) Int() int {
|
||||
return int(c.value)
|
||||
}
|
||||
|
||||
// MarshalWrite writes the uint64 value to the provided writer in BigEndian order.
|
||||
func (c *Uint64Codec) MarshalWrite(w io.Writer) error {
|
||||
return binary.Write(w, binary.BigEndian, c.value)
|
||||
}
|
||||
|
||||
// UnmarshalRead reads a uint64 value from the provided reader in BigEndian order.
|
||||
func (c *Uint64Codec) UnmarshalRead(r io.Reader) error {
|
||||
return binary.Read(r, binary.BigEndian, &c.value)
|
||||
}
|
||||
66
database/indexes/types/number/uint64_test.go
Normal file
66
database/indexes/types/number/uint64_test.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package number
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"lukechampine.com/frand"
|
||||
)
|
||||
|
||||
func TestUint64Codec(t *testing.T) {
|
||||
// Helper function to generate random 64-bit integers
|
||||
generateRandomUint64 := func() uint64 {
|
||||
return frand.Uint64n(math.MaxUint64) // math.MaxUint64 == 18446744073709551615
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ { // Run test 100 times for random values
|
||||
// Generate a random value
|
||||
randomUint64 := generateRandomUint64()
|
||||
randomInt := int(randomUint64)
|
||||
|
||||
// Create a new codec
|
||||
codec := new(Uint64Codec)
|
||||
|
||||
// Test UInt64 setter and getter
|
||||
codec.SetUint64(randomUint64)
|
||||
if codec.Uint64() != randomUint64 {
|
||||
t.Fatalf("Uint64 mismatch: got %d, expected %d", codec.Uint64(), randomUint64)
|
||||
}
|
||||
|
||||
// Test Int setter and getter
|
||||
codec.SetInt(randomInt)
|
||||
if codec.Int() != randomInt {
|
||||
t.Fatalf("Int mismatch: got %d, expected %d", codec.Int(), randomInt)
|
||||
}
|
||||
|
||||
// Test encoding to []byte and decoding back
|
||||
bufEnc := new(bytes.Buffer)
|
||||
|
||||
// MarshalWrite
|
||||
err := codec.MarshalWrite(bufEnc)
|
||||
if err != nil {
|
||||
t.Fatalf("MarshalWrite failed: %v", err)
|
||||
}
|
||||
encoded := bufEnc.Bytes()
|
||||
|
||||
// Create a buffer for decoding
|
||||
bufDec := bytes.NewBuffer(encoded)
|
||||
|
||||
// Decode back the value
|
||||
decodedCodec := new(Uint64Codec)
|
||||
err = decodedCodec.UnmarshalRead(bufDec)
|
||||
if err != nil {
|
||||
t.Fatalf("UnmarshalRead failed: %v", err)
|
||||
}
|
||||
|
||||
if decodedCodec.Uint64() != randomUint64 {
|
||||
t.Fatalf("Decoded value mismatch: got %d, expected %d", decodedCodec.Uint64(), randomUint64)
|
||||
}
|
||||
|
||||
// Compare encoded bytes to ensure correctness
|
||||
if !bytes.Equal(encoded, bufEnc.Bytes()) {
|
||||
t.Fatalf("Byte encoding mismatch: got %v, expected %v", bufEnc.Bytes(), encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user