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) }