Files
bin/bin_test.go
2024-10-31 03:55:08 +02:00

706 lines
14 KiB
Go
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bin
import (
"bytes"
"fmt"
"math"
"strconv"
"testing"
"time"
)
const (
max7b uint64 = 127
max14b uint64 = 16383
max21b uint64 = 2097151
max28b uint64 = 268435455
max35b uint64 = 34359738367
max42b uint64 = 4398046511103
max49b uint64 = 562949953421311
max56b uint64 = 72057594037927935
max24b uint64 = 16777215
max40b uint64 = 1099511627775
max48b uint64 = 281474976710655
)
type UintAndSize struct {
Value uint64
Size int
}
/*
func TestVarUint64(t *testing.T) {
// числа между 0, 1 и MaxUint64 - это 2 в степени кратной семи
// плюс предыдущее число. Например: 2**7-1, 2**7
var nums = []UintAndSize{
{0, 1},
{1, 1},
{max7b, 1},
{max7b + 1, 2},
{max14b, 2},
{max14b + 1, 3},
{max21b, 3},
{max21b + 1, 4},
{max28b, 4},
{max28b + 1, 5},
{max35b, 5},
{max35b + 1, 6},
{max42b, 6},
{max42b + 1, 7},
{max49b, 7},
{max49b + 1, 8},
{max56b, 8},
{max56b + 1, 9},
{math.MaxUint64, 9},
}
buf := bytes.NewBuffer(nil)
for _, num := range nums {
buf.Reset()
n := PutVarUint64(buf, num.Value)
if n != num.Size {
t.Fatalf("Encoded size %d != estimated size %d for num %d\n", n, num.Size, num.Value)
}
encoded := buf.Bytes()
x, err := GetVarUint64(bytes.NewBuffer(encoded))
if err != nil {
t.Fatalf("GetVarUint64 error: %s\n", err)
}
if x != num.Value {
t.Fatalf("Origin num %d != decoded num %d. Buffer: %v\n", num.Value, x, encoded)
}
}
}
func TestVarUint32(t *testing.T) {
// числа между 0, 1 и MaxUint64 - это 2 в степени кратной семи
// плюс предыдущее число. Например: 2**7-1, 2**7
var nums = []UintAndSize{
{0, 1},
{1, 1},
{max7b, 1},
{max7b + 1, 2},
{max14b, 2},
{max14b + 1, 3},
{max21b, 3},
{max21b + 1, 4},
{max28b, 4},
{max28b + 1, 5},
{math.MaxUint32, 5},
}
buf := bytes.NewBuffer(nil)
for _, num := range nums {
buf.Reset()
origin := uint32(num.Value)
n := PutVarUint32(buf, origin)
if n != num.Size {
t.Fatalf("Encoded size %d != estimated size %d for num %d\n", n, num.Size, origin)
}
encoded := buf.Bytes()
x, err := GetVarUint32(bytes.NewBuffer(encoded))
if err != nil {
t.Fatalf("GetVarUint32 error: %s\n", err)
}
if x != origin {
t.Fatalf("Origin num %d != decoded num %d. Buffer: %v\n", origin, x, encoded)
}
}
}
*/
/*
func TestMaxUint64(t *testing.T) {
// числа между 0, 1 и MaxUint64 - это 2 в степени кратной семи
// плюс предыдущее число. Например: 2**7-1, 2**7
var nums = []UintAndSize{
{0, 1},
{1, 1},
{math.MaxUint8, 1},
{math.MaxUint8 + 1, 2},
{math.MaxUint16, 2},
{math.MaxUint16 + 1, 3},
{max24b, 3},
{max24b + 1, 4},
{math.MaxUint32, 4},
{math.MaxUint32 + 1, 5},
{max40b, 5},
{max40b + 1, 6},
{max48b, 6},
{max48b + 1, 7},
{max56b, 7},
{max56b + 1, 8},
{math.MaxUint64, 8},
}
buf := bytes.NewBuffer(nil)
for _, num := range nums {
buf.Reset()
n := PutMaxUint64(buf, num.Value)
if n != num.Size {
t.Fatalf("Encoded size %d != estimated size %d for num %d\n", n, num.Size, num.Value)
}
encoded := buf.Bytes()
x, err := GetMaxUint64(bytes.NewBuffer(encoded), n)
if err != nil {
t.Fatalf("GetMaxUint64 error: %s\n", err)
}
if x != num.Value {
t.Fatalf("Origin num %d != decoded num %d. Buffer: %v\n", num.Value, x, encoded)
}
}
}
*/
func TestFloat32(t *testing.T) {
buf := []byte{234, 171, 234, 171, 234, 171, 234, 171, 234, 171}
r := bytes.NewBuffer(buf)
num, err := ReadFloat32(r, HL)
if err != nil {
t.Fatal(err)
}
fmt.Printf("float32: %f\n", num)
x := float64(num)
fmt.Printf("float64: %f\n", x*4)
fmt.Printf("int64: %d\n", int64(x)+10)
mid := make([]byte, 4)
err = PutFloat32(mid, num, HL)
if err != nil {
t.Fatal(err)
}
fmt.Printf("%d\n", mid)
}
func Test6bDateTime(t *testing.T) {
//
now := time.Now()
now = now.In(time.UTC)
w := bytes.NewBuffer(nil)
Write6bDateTime(w, now)
arr := w.Bytes()
fmt.Printf("%s: %v, %d\n", now, arr, now.Unix())
r := bytes.NewBuffer(arr)
tm, _ := Read6bDateTime(r)
fmt.Printf("%s: %d\n", tm, tm.Unix())
}
func TestSplitFloat(t *testing.T) {
f := 650179.6985999999 // округляет вниз .6985
total := 8.2291999999 // округляет вверх 8.2292
n := SplitFloat(f, 4)
x := SplitFloat(total, 4)
fmt.Printf("int: %d, frac: %d\n", n.Int, n.Frac)
fmt.Printf("total int: %d, frac: %d\n", x.Int, x.Frac)
}
func TestSplitFloat2(t *testing.T) {
//prev := 65032252.8724999875 // округляет вниз .6985
//total := 9.2449999973 // округляет вверх 8.2292
fracDigits := 4
floatPrev := 65000005.499980002
floatTotal := 3.5000800019
prev := SplitFloat(floatPrev, fracDigits)
total := SplitFloat(floatTotal, fracDigits)
fmt.Printf("prev: i=%d, f=%d\n", prev.Int, prev.Frac)
fmt.Printf("total i=%d, f=%d\n", total.Int, total.Frac)
value := SplitFloat(floatPrev+floatTotal, fracDigits)
fmt.Printf("real i=%d, f=%d\n", value.Int, value.Frac)
calcInt := prev.Int + total.Int
calcFrac := prev.Frac + total.Frac
if calcFrac >= 10000 {
calcFrac -= 10000
calcInt += 1
}
fmt.Printf("calc i=%d, f=%d\n", calcInt, calcFrac)
fmt.Printf("\n%.9f\n", 10000000.999999999)
}
func TestSplitFloat3(t *testing.T) {
f := 2806262383595.7373 // округляет вниз .6985
n := SplitFloat(f, 4)
fmt.Printf("int: %d, frac: %d\n", n.Int, n.Frac)
}
func TestBitOps(t *testing.T) {
var b byte = 255
var bitNo byte = 7
fmt.Printf("%08b\n", UnsetBit(b, bitNo))
fmt.Printf("%08b\n", SetBit(UnsetBit(b, bitNo), bitNo))
}
func TestDecodeFloat(t *testing.T) {
var buf = []byte{0xCE, 0x6E, 0x6B, 0x28}
f1, err := GetFloat32(buf, LH)
if err != nil {
panic(err)
}
f2, err := GetFloat32(buf, HL)
if err != nil {
panic(err)
}
fmt.Printf("LH: %v\nHL: %v\nBIN: %08b\n\n", f1, f2, buf)
n, err := strconv.ParseFloat("-1e9", 32)
if err != nil {
panic(err)
}
f := float32(n)
var arr = []byte{0, 0, 0, 0}
PutFloat32(arr, f, HL)
fmt.Printf("%v\nBIN: %08b\n", f, arr)
}
// Тесты массивов (для написания СУБД). Когда в байтовом виде записан массив из N элементов,
// фиксированного размера (например 4-байтовый uint32 или 2-байтовый uint16). Из массива
// нужно удалять элементы по индексу, либо в массив вставлять по индексу (чтобы другие
// элементы "подвинулись").
type _DeleteArrElemTestCase struct {
Arr []byte
Qty int
ElemSize int
Idx int
Result []byte
}
type _InsertArrElemTestCase struct {
Arr []byte
Qty int
Elem []byte
Idx int
Result []byte
}
func TestDeleteArrElem(t *testing.T) {
originArr := []byte{1, 1, 2, 2, 3, 3, 255, 0, 0, 0}
testCases := []_DeleteArrElemTestCase{
{
Arr: originArr,
Qty: 3,
ElemSize: 2,
Idx: 0,
Result: []byte{2, 2, 3, 3, 0, 0, 255, 0, 0, 0},
},
{
Arr: originArr,
Qty: 3,
ElemSize: 2,
Idx: 1,
Result: []byte{1, 1, 3, 3, 0, 0, 255, 0, 0, 0},
},
{
Arr: originArr,
Qty: 3,
ElemSize: 2,
Idx: 2,
Result: []byte{1, 1, 2, 2, 0, 0, 255, 0, 0, 0},
},
}
for _, testCase := range testCases {
arrcopy := make([]byte, len(testCase.Arr))
copy(arrcopy, testCase.Arr)
DeleteArrElem(arrcopy, testCase.Qty, testCase.ElemSize, testCase.Idx)
if !bytes.Equal(arrcopy, testCase.Result) {
t.Fatalf(`
Source: %v
Estimate: %v
Real: %v`,
testCase.Arr, testCase.Result, arrcopy)
}
}
}
func TestInsertArrElem(t *testing.T) {
originArr := []byte{1, 1, 2, 2, 0, 0, 255, 0}
elem := []byte{7, 7}
testCases := []_InsertArrElemTestCase{
{
Arr: originArr,
Qty: 2,
Elem: elem,
Idx: 0,
Result: []byte{7, 7, 1, 1, 2, 2, 255, 0},
},
{
Arr: originArr,
Qty: 2,
Elem: elem,
Idx: 1,
Result: []byte{1, 1, 7, 7, 2, 2, 255, 0},
},
{
Arr: originArr,
Qty: 2,
Elem: elem,
Idx: 2,
Result: []byte{1, 1, 2, 2, 7, 7, 255, 0},
},
}
for _, testCase := range testCases {
arrcopy := make([]byte, len(testCase.Arr))
copy(arrcopy, testCase.Arr)
InsertArrElem(arrcopy, testCase.Qty, testCase.Elem, testCase.Idx)
if !bytes.Equal(arrcopy, testCase.Result) {
t.Fatalf(`
Source: %v
Estimate: %v
Real: %v`,
testCase.Arr, testCase.Result, arrcopy)
}
}
}
func TestDeleteReverseArrElem(t *testing.T) {
originArr := []byte{0, 0, 255, 3, 3, 2, 2, 1, 1}
testCases := []_DeleteArrElemTestCase{
{
Arr: originArr,
Qty: 3,
ElemSize: 2,
Idx: 0,
Result: []byte{0, 0, 255, 0, 0, 3, 3, 2, 2},
},
{
Arr: originArr,
Qty: 3,
ElemSize: 2,
Idx: 1,
Result: []byte{0, 0, 255, 0, 0, 3, 3, 1, 1},
},
{
Arr: originArr,
Qty: 3,
ElemSize: 2,
Idx: 2,
Result: []byte{0, 0, 255, 0, 0, 2, 2, 1, 1},
},
}
for _, testCase := range testCases {
arrcopy := make([]byte, len(testCase.Arr))
copy(arrcopy, testCase.Arr)
DeleteReverseArrElem(arrcopy, testCase.Qty, testCase.ElemSize, testCase.Idx)
if !bytes.Equal(arrcopy, testCase.Result) {
t.Fatalf(`
Source: %v
Estimate: %v
Real: %v`,
testCase.Arr, testCase.Result, arrcopy)
}
}
}
func TestInsertReverseArrElem(t *testing.T) {
originArr := []byte{0, 255, 0, 0, 2, 2, 1, 1}
elem := []byte{7, 7}
testCases := []_InsertArrElemTestCase{
{
Arr: originArr,
Qty: 2,
Elem: elem,
Idx: 0,
Result: []byte{0, 255, 2, 2, 1, 1, 7, 7},
},
{
Arr: originArr,
Qty: 2,
Elem: elem,
Idx: 1,
Result: []byte{0, 255, 2, 2, 7, 7, 1, 1},
},
{
Arr: originArr,
Qty: 2,
Elem: elem,
Idx: 2,
Result: []byte{0, 255, 7, 7, 2, 2, 1, 1},
},
}
for _, testCase := range testCases {
arrcopy := make([]byte, len(testCase.Arr))
copy(arrcopy, testCase.Arr)
InsertReverseArrElem(arrcopy, testCase.Qty, testCase.Elem, testCase.Idx)
if !bytes.Equal(arrcopy, testCase.Result) {
t.Fatalf(`
Source: %v
Estimate: %v
Real: %v`,
testCase.Arr, testCase.Result, arrcopy)
}
}
}
func TestCompareToArrElem(t *testing.T) {
arr := []byte{1, 2, 3, 4}
elem := []byte{5, 2}
code := compareToArrElem(arr, elem, 1, HL)
fmt.Printf("code: %d\n", code)
}
type _FindArrElemTestCase struct {
Elem []byte // элемент, который будем искать в массиве
// Результат поиска - индекс и флаг
Idx int
Found bool
}
func TestFindArrElem(t *testing.T) {
arr := []byte{2, 2, 5, 5, 7, 7, 0, 0}
testCases := []_FindArrElemTestCase{
{
Elem: []byte{1, 1},
Idx: 0,
Found: false,
},
{
Elem: []byte{2, 2},
Idx: 0,
Found: true,
},
{
Elem: []byte{3, 3},
Idx: 1,
Found: false,
},
{
Elem: []byte{5, 5},
Idx: 1,
Found: true,
},
{
Elem: []byte{6, 6},
Idx: 2,
Found: false,
},
{
Elem: []byte{7, 7},
Idx: 2,
Found: true,
},
{
Elem: []byte{8, 8},
Idx: 3,
Found: false,
},
}
errorPattern := `Case:
byteOrder: %s
elem: %v
idx: %d
found: %t
Result:
idx: %d
found: %t
`
var (
idx int
found bool
)
for _, testCase := range testCases {
idx, found = FindArrElem(arr, 3, testCase.Elem, LH)
if idx != testCase.Idx || found != testCase.Found {
t.Fatalf(errorPattern,
LH, testCase.Elem, testCase.Idx, testCase.Found, idx, found)
}
// Тоже самое, но с другим порядком байт
idx, found = FindArrElem(arr, 3, testCase.Elem, HL)
if idx != testCase.Idx || found != testCase.Found {
t.Fatalf(errorPattern,
HL, testCase.Elem, testCase.Idx, testCase.Found, idx, found)
}
}
//fmt.Printf("idx: %d, found: %t\n", idx, found)
}
func TestFloatToUint(t *testing.T) {
//f =
}
func TestIntToUint(t *testing.T) {
var i int64 = 20 //-math.MaxInt64 - 1
u := Int64AsUint64(i)
fmt.Printf("%v\n", u)
x := Uint64AsInt64(u)
fmt.Printf("%v\n", x)
}
var bytesOrders = []ByteOrder{LH, HL}
func TestInt24(t *testing.T) {
var nums = []int32{-1, 0, 1, -4915195, 4915195}
for _, num := range nums {
for _, byteOrder := range bytesOrders {
buf := bytes.NewBuffer(nil)
err := WriteInt24(buf, num, byteOrder)
if err != nil {
t.Fatalf("%s; num=%d; byteOrder=%s\n", err, num, byteOrder)
}
unpacked, err := ReadInt24(buf, byteOrder)
if err != nil {
t.Fatal(err)
}
if unpacked != num {
t.Fatalf("num %d != unpacked %d (byteOrder=%s)\n", num, unpacked, byteOrder)
}
}
}
}
func TestInt48(t *testing.T) {
var nums = []int64{-1, 0, 1, -4915195, 4915195}
for _, num := range nums {
for _, byteOrder := range bytesOrders {
buf := bytes.NewBuffer(nil)
err := WriteInt48(buf, num, byteOrder)
if err != nil {
t.Fatalf("%s; num=%d; byteOrder=%s\n", err, num, byteOrder)
}
unpacked, err := ReadInt48(buf, byteOrder)
if err != nil {
t.Fatal(err)
}
if unpacked != num {
t.Fatalf("num %d != unpacked %d (byteOrder=%s)\n", num, unpacked, byteOrder)
}
}
}
}
func TestInt32(t *testing.T) {
buf := bytes.NewBuffer(nil)
byteOrder := HL
err := WriteInt32(buf, ^math.MaxInt32, byteOrder)
if err != nil {
t.Fatal(err)
}
fmt.Printf("%08b\n", buf.Bytes())
num, err := ReadInt32(buf, byteOrder)
if err != nil {
t.Fatal(err)
}
fmt.Println(num)
}
func TestVarSize(t *testing.T) {
var (
buf = bytes.NewBuffer(nil)
nums = []int{
0,
1,
127, // 7
16383, // 14
2097151, // 21
268435455, // 28
34359738367, // 35
4398046511103, // 42
562949953421311, // 49
72057594037927935, // 56
9223372036854775807, // 63
}
)
for _, num := range nums {
WriteVarSize(buf, num)
decoded, err := ReadVarSize(buf)
if err != nil {
t.Fatal(err)
}
if decoded != num {
t.Fatalf("num %d decoded as %d\n", num, decoded)
}
buf.Reset()
}
}