Files
2026-07-13 12:32:25 +08:00

296 lines
12 KiB
Go

// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"bytes"
"math"
"sort"
"testing"
"github.com/stretchr/testify/require"
)
// TestWriterReader tests that the writer can round-trip with the reader, preserving data while writing every data type.
func TestWriterReader(t *testing.T) {
writer := NewWriter(0)
writer.Bool(false)
writer.Bool(true)
writer.Int8(-128)
writer.Int8(-57)
writer.Int8(0)
writer.Int8(35)
writer.Int8(127)
writer.Int16(-32768)
writer.Int16(-25756)
writer.Int16(0)
writer.Int16(11527)
writer.Int16(32767)
writer.Int32(-2147483648)
writer.Int32(-4764286)
writer.Int32(0)
writer.Int32(17395298)
writer.Int32(2147483647)
writer.Int64(-9223372036854775808)
writer.Int64(-716243597812645)
writer.Int64(0)
writer.Int64(12784331275341)
writer.Int64(9223372036854775807)
writer.Uint8(0)
writer.Uint8(126)
writer.Uint8(255)
writer.Uint16(0)
writer.Uint16(8465)
writer.Uint16(65535)
writer.Uint32(0)
writer.Uint32(217357235)
writer.Uint32(4294967295)
writer.Uint64(0)
writer.Uint64(12465143251276)
writer.Uint64(18446744073709551615)
writer.Float32(-1716.5625)
writer.Float32(0)
writer.Float32(27465)
writer.Float64(-104451.625)
writer.Float64(0)
writer.Float64(26112.40625)
writer.VariableInt(-9223372036854775808)
writer.VariableInt(-716243597812645)
writer.VariableInt(0)
writer.VariableInt(12784331275341)
writer.VariableInt(9223372036854775807)
writer.VariableUint(0)
writer.VariableUint(12465143251276)
writer.VariableUint(18446744073709551615)
writer.String("")
writer.String("abc123")
writer.String("This is a full sentence. 素晴らしい")
writer.BoolSlice([]bool{true, false, false, true})
writer.Int8Slice([]int8{-128, -57, 0, 35, 127})
writer.Int16Slice([]int16{-32768, -25756, 0, 11527, 32767})
writer.Int32Slice([]int32{-2147483648, -4764286, 0, 17395298, 2147483647})
writer.Int64Slice([]int64{-9223372036854775808, -716243597812645, 0, 12784331275341, 9223372036854775807})
writer.Uint8Slice([]uint8{0, 126, 255})
writer.Uint16Slice([]uint16{0, 8465, 65535})
writer.Uint32Slice([]uint32{0, 217357235, 4294967295})
writer.Uint64Slice([]uint64{0, 12465143251276, 18446744073709551615})
writer.Float32Slice([]float32{-1716.5625, 0, 27465})
writer.Float64Slice([]float64{-104451.625, 0, 26112.40625})
writer.VariableIntSlice([]int64{-9223372036854775808, -716243597812645, 0, 12784331275341, 9223372036854775807})
writer.VariableUintSlice([]uint64{0, 12465143251276, 18446744073709551615})
writer.StringSlice([]string{"This", "is", "a", "string", "test."})
reader := NewReader(writer.Data())
require.Equal(t, false, reader.Bool())
require.Equal(t, true, reader.Bool())
require.Equal(t, int8(-128), reader.Int8())
require.Equal(t, int8(-57), reader.Int8())
require.Equal(t, int8(0), reader.Int8())
require.Equal(t, int8(35), reader.Int8())
require.Equal(t, int8(127), reader.Int8())
require.Equal(t, int16(-32768), reader.Int16())
require.Equal(t, int16(-25756), reader.Int16())
require.Equal(t, int16(0), reader.Int16())
require.Equal(t, int16(11527), reader.Int16())
require.Equal(t, int16(32767), reader.Int16())
require.Equal(t, int32(-2147483648), reader.Int32())
require.Equal(t, int32(-4764286), reader.Int32())
require.Equal(t, int32(0), reader.Int32())
require.Equal(t, int32(17395298), reader.Int32())
require.Equal(t, int32(2147483647), reader.Int32())
require.Equal(t, int64(-9223372036854775808), reader.Int64())
require.Equal(t, int64(-716243597812645), reader.Int64())
require.Equal(t, int64(0), reader.Int64())
require.Equal(t, int64(12784331275341), reader.Int64())
require.Equal(t, int64(9223372036854775807), reader.Int64())
require.Equal(t, uint8(0), reader.Uint8())
require.Equal(t, uint8(126), reader.Uint8())
require.Equal(t, uint8(255), reader.Uint8())
require.Equal(t, uint16(0), reader.Uint16())
require.Equal(t, uint16(8465), reader.Uint16())
require.Equal(t, uint16(65535), reader.Uint16())
require.Equal(t, uint32(0), reader.Uint32())
require.Equal(t, uint32(217357235), reader.Uint32())
require.Equal(t, uint32(4294967295), reader.Uint32())
require.Equal(t, uint64(0), reader.Uint64())
require.Equal(t, uint64(12465143251276), reader.Uint64())
require.Equal(t, uint64(18446744073709551615), reader.Uint64())
require.Equal(t, float32(-1716.5625), reader.Float32())
require.Equal(t, float32(0), reader.Float32())
require.Equal(t, float32(27465), reader.Float32())
require.Equal(t, float64(-104451.625), reader.Float64())
require.Equal(t, float64(0), reader.Float64())
require.Equal(t, float64(26112.40625), reader.Float64())
require.Equal(t, int64(-9223372036854775808), reader.VariableInt())
require.Equal(t, int64(-716243597812645), reader.VariableInt())
require.Equal(t, int64(0), reader.VariableInt())
require.Equal(t, int64(12784331275341), reader.VariableInt())
require.Equal(t, int64(9223372036854775807), reader.VariableInt())
require.Equal(t, uint64(0), reader.VariableUint())
require.Equal(t, uint64(12465143251276), reader.VariableUint())
require.Equal(t, uint64(18446744073709551615), reader.VariableUint())
require.Equal(t, "", reader.String())
require.Equal(t, "abc123", reader.String())
require.Equal(t, "This is a full sentence. 素晴らしい", reader.String())
require.Equal(t, []bool{true, false, false, true}, reader.BoolSlice())
require.Equal(t, []int8{-128, -57, 0, 35, 127}, reader.Int8Slice())
require.Equal(t, []int16{-32768, -25756, 0, 11527, 32767}, reader.Int16Slice())
require.Equal(t, []int32{-2147483648, -4764286, 0, 17395298, 2147483647}, reader.Int32Slice())
require.Equal(t, []int64{-9223372036854775808, -716243597812645, 0, 12784331275341, 9223372036854775807}, reader.Int64Slice())
require.Equal(t, []uint8{0, 126, 255}, reader.Uint8Slice())
require.Equal(t, []uint16{0, 8465, 65535}, reader.Uint16Slice())
require.Equal(t, []uint32{0, 217357235, 4294967295}, reader.Uint32Slice())
require.Equal(t, []uint64{0, 12465143251276, 18446744073709551615}, reader.Uint64Slice())
require.Equal(t, []float32{-1716.5625, 0, 27465}, reader.Float32Slice())
require.Equal(t, []float64{-104451.625, 0, 26112.40625}, reader.Float64Slice())
require.Equal(t, []int64{-9223372036854775808, -716243597812645, 0, 12784331275341, 9223372036854775807}, reader.VariableIntSlice())
require.Equal(t, []uint64{0, 12465143251276, 18446744073709551615}, reader.VariableUintSlice())
require.Equal(t, []string{"This", "is", "a", "string", "test."}, reader.StringSlice())
}
// TestWriterOrder ensures that some types that are traditionally not byte-comparable when serialized are
// byte-comparable using the writer.
func TestWriterOrder(t *testing.T) {
t.Run("int8", func(t *testing.T) {
var serializedData [][]byte
integers := []int8{8, -1, 99, 0, -45, -103, 4, 127, 1, 10, 0, -128, -33, 56}
for _, integer := range integers {
writer := NewWriter(1)
writer.Int8(integer)
serializedData = append(serializedData, writer.Data())
}
sort.Slice(integers, func(i, j int) bool {
return integers[i] < integers[j]
})
sort.Slice(serializedData, func(i, j int) bool {
return bytes.Compare(serializedData[i], serializedData[j]) == -1
})
deserializedIntegers := make([]int8, len(integers))
for i, data := range serializedData {
reader := NewReader(data)
deserializedIntegers[i] = reader.Int8()
}
require.Equal(t, integers, deserializedIntegers)
})
t.Run("int16", func(t *testing.T) {
var serializedData [][]byte
integers := []int16{8, -1, 999, 0, -455, -103, 4, 32767, 1, 100, 0, -32768, -33, 56}
for _, integer := range integers {
writer := NewWriter(2)
writer.Int16(integer)
serializedData = append(serializedData, writer.Data())
}
sort.Slice(integers, func(i, j int) bool {
return integers[i] < integers[j]
})
sort.Slice(serializedData, func(i, j int) bool {
return bytes.Compare(serializedData[i], serializedData[j]) == -1
})
deserializedIntegers := make([]int16, len(integers))
for i, data := range serializedData {
reader := NewReader(data)
deserializedIntegers[i] = reader.Int16()
}
require.Equal(t, integers, deserializedIntegers)
})
t.Run("int32", func(t *testing.T) {
var serializedData [][]byte
integers := []int32{8, -1, 999, 0, -4559775, -103, 4, 2147483647, 1, 100, 0, -2147483648, -33, 5667845}
for _, integer := range integers {
writer := NewWriter(4)
writer.Int32(integer)
serializedData = append(serializedData, writer.Data())
}
sort.Slice(integers, func(i, j int) bool {
return integers[i] < integers[j]
})
sort.Slice(serializedData, func(i, j int) bool {
return bytes.Compare(serializedData[i], serializedData[j]) == -1
})
deserializedIntegers := make([]int32, len(integers))
for i, data := range serializedData {
reader := NewReader(data)
deserializedIntegers[i] = reader.Int32()
}
require.Equal(t, integers, deserializedIntegers)
})
t.Run("int64", func(t *testing.T) {
var serializedData [][]byte
integers := []int64{8, -1, 999, 0, -4559775534255, -103, 4, 9223372036854775807, 1, 100, 0, -9223372036854775808, -33, 566782356235645}
for _, integer := range integers {
writer := NewWriter(8)
writer.Int64(integer)
serializedData = append(serializedData, writer.Data())
}
sort.Slice(integers, func(i, j int) bool {
return integers[i] < integers[j]
})
sort.Slice(serializedData, func(i, j int) bool {
return bytes.Compare(serializedData[i], serializedData[j]) == -1
})
deserializedIntegers := make([]int64, len(integers))
for i, data := range serializedData {
reader := NewReader(data)
deserializedIntegers[i] = reader.Int64()
}
require.Equal(t, integers, deserializedIntegers)
})
t.Run("float32", func(t *testing.T) {
var serializedData [][]byte
floats := []float32{8, -1.123479648834723, 999, 0, -4559775534255, -103.72453, 4, 3.40282347e+38,
9223372036854775807, 1, -3.40282347e+38, 100.1386723987453, 0, -9223372036854775808, -33,
float32(math.Inf(1)), float32(math.Inf(-1)), 566782356235645.1345}
for _, integer := range floats {
writer := NewWriter(4)
writer.Float32(integer)
serializedData = append(serializedData, writer.Data())
}
sort.Slice(floats, func(i, j int) bool {
return floats[i] < floats[j]
})
sort.Slice(serializedData, func(i, j int) bool {
return bytes.Compare(serializedData[i], serializedData[j]) == -1
})
deserializedFloats := make([]float32, len(floats))
for i, data := range serializedData {
reader := NewReader(data)
deserializedFloats[i] = reader.Float32()
}
require.Equal(t, floats, deserializedFloats)
})
t.Run("float64", func(t *testing.T) {
var serializedData [][]byte
floats := []float64{8, -1.123479648834723, 999, 0, -4559775534255, -103.72453, 4, 1.7976931348623157e+308,
9223372036854775807, 1, -1.7976931348623157e+308, 100.1386723987453, 0, -9223372036854775808, -33,
math.Inf(1), math.Inf(-1), 566782356235645.1345}
for _, integer := range floats {
writer := NewWriter(8)
writer.Float64(integer)
serializedData = append(serializedData, writer.Data())
}
sort.Slice(floats, func(i, j int) bool {
return floats[i] < floats[j]
})
sort.Slice(serializedData, func(i, j int) bool {
return bytes.Compare(serializedData[i], serializedData[j]) == -1
})
deserializedFloats := make([]float64, len(floats))
for i, data := range serializedData {
reader := NewReader(data)
deserializedFloats[i] = reader.Float64()
}
require.Equal(t, floats, deserializedFloats)
})
}