From 1ec02194735a43c8fd6774f245c67bcd275fc946 Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Thu, 4 Apr 2019 23:00:21 +0800 Subject: [PATCH 1/8] add gbinary unit tests --- g/encoding/gbinary/gbinary_test.go | 135 +++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 g/encoding/gbinary/gbinary_test.go diff --git a/g/encoding/gbinary/gbinary_test.go b/g/encoding/gbinary/gbinary_test.go new file mode 100644 index 000000000..2cb64a848 --- /dev/null +++ b/g/encoding/gbinary/gbinary_test.go @@ -0,0 +1,135 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary_test + +import ( + "github.com/gogf/gf/g/encoding/gbinary" + "github.com/gogf/gf/g/test/gtest" + "math" + "testing" +) + +var testData = map[string]interface{}{ + "nil": nil, + "int": int(123), + "int8": int8(-99), + "int8.max": math.MaxInt8, + "int16": int16(123), + "int16.max": math.MaxInt16, + "int32": int32(-199), + "int32.max": math.MaxInt32, + "int64": int64(123), + "int64.max": math.MaxInt64, + "uint": uint(123), + "uint8": uint8(123), + "uint8.max": math.MaxUint8, + "uint16": uint16(9999), + "uint16.max": math.MaxUint16, + "uint32": uint32(123), + "uint32.max": math.MaxUint32, + "uint64": uint64(123), + "uint64.max": math.MaxUint32 + 1, + "bool.true": true, + "bool.false": false, + "string": "hehe haha", + "byte": []byte("hehe haha"), + "float32": float32(123.456), + "float32.max": math.MaxFloat32, + "float64": float64(123.456), + "float64.max": math.MaxFloat64, +} + +func TestEncodeAndDecode(t *testing.T) { + for k, v := range testData { + ve := gbinary.Encode(v) + ve1 := gbinary.EncodeByLength(len(ve), v) + + //t.Logf("%s:%v, encoded:%v\n", k, v, ve) + switch v.(type) { + case int: + gtest.Assert(gbinary.DecodeToInt(ve), v) + gtest.Assert(gbinary.DecodeToInt(ve1), v) + case int8: + gtest.Assert(gbinary.DecodeToInt8(ve), v) + gtest.Assert(gbinary.DecodeToInt8(ve1), v) + case int16: + gtest.Assert(gbinary.DecodeToInt16(ve), v) + gtest.Assert(gbinary.DecodeToInt16(ve1), v) + case int32: + gtest.Assert(gbinary.DecodeToInt32(ve), v) + gtest.Assert(gbinary.DecodeToInt32(ve1), v) + case int64: + gtest.Assert(gbinary.DecodeToInt64(ve), v) + gtest.Assert(gbinary.DecodeToInt64(ve1), v) + case uint: + gtest.Assert(gbinary.DecodeToUint(ve), v) + gtest.Assert(gbinary.DecodeToUint(ve1), v) + case uint8: + gtest.Assert(gbinary.DecodeToUint8(ve), v) + gtest.Assert(gbinary.DecodeToUint8(ve1), v) + case uint16: + gtest.Assert(gbinary.DecodeToUint16(ve1), v) + gtest.Assert(gbinary.DecodeToUint16(ve), v) + case uint32: + gtest.Assert(gbinary.DecodeToUint32(ve1), v) + gtest.Assert(gbinary.DecodeToUint32(ve), v) + case uint64: + gtest.Assert(gbinary.DecodeToUint64(ve), v) + gtest.Assert(gbinary.DecodeToUint64(ve1), v) + case bool: + gtest.Assert(gbinary.DecodeToBool(ve), v) + gtest.Assert(gbinary.DecodeToBool(ve1), v) + case string: + gtest.Assert(gbinary.DecodeToString(ve), v) + gtest.Assert(gbinary.DecodeToString(ve1), v) + case float32: + gtest.Assert(gbinary.DecodeToFloat32(ve), v) + gtest.Assert(gbinary.DecodeToFloat32(ve1), v) + case float64: + gtest.Assert(gbinary.DecodeToFloat64(ve), v) + gtest.Assert(gbinary.DecodeToFloat64(ve1), v) + default: + if v == nil { + continue + } + res := make([]byte, len(ve)) + err := gbinary.Decode(ve, res) + if err != nil { + t.Errorf("test data: %s, %v, error:%v", k, v, err) + } + gtest.Assert(res, v) + } + } +} + +type User struct { + Name string + Age int + Url string +} + +func TestEncodeStruct(t *testing.T) { + user := User{"wenzi1", 999, "www.baidu.com"} + ve := gbinary.Encode(user) + s := gbinary.DecodeToString(ve) + gtest.Assert(string(s), s) +} + +var testBitData = []int{0, 99, 122, 129, 222, 999, 22322} + +func TestBits(t *testing.T) { + for i := range testBitData { + bits := make([]gbinary.Bit, 0) + res := gbinary.EncodeBits(bits, testBitData[i], 64) + + gtest.Assert(gbinary.DecodeBits(res), testBitData[i]) + gtest.Assert(gbinary.DecodeBitsToUint(res), uint(testBitData[i])) + + gtest.Assert(gbinary.DecodeBytesToBits(gbinary.EncodeBitsToBytes(res)), res) + } + +} From 779ad93bcbddee472d06d07fa09e885fee9df165 Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Thu, 4 Apr 2019 23:02:00 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E5=8F=82=E6=95=B0=E4=B8=BAnil=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E7=89=B9=E6=AE=8A=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/encoding/gbinary/gbinary.go | 376 ++++++++++++++++++---------------- 1 file changed, 198 insertions(+), 178 deletions(-) diff --git a/g/encoding/gbinary/gbinary.go b/g/encoding/gbinary/gbinary.go index 4a133b0d5..532c38065 100644 --- a/g/encoding/gbinary/gbinary.go +++ b/g/encoding/gbinary/gbinary.go @@ -8,10 +8,10 @@ package gbinary import ( - "fmt" - "math" - "bytes" - "encoding/binary" + "bytes" + "encoding/binary" + "fmt" + "math" ) // 二进制位(0|1) @@ -20,304 +20,324 @@ type Bit int8 // 针对基本类型进行二进制打包,支持的基本数据类型包括:int/8/16/32/64、uint/8/16/32/64、float32/64、bool、string、[]byte // 其他未知类型使用 fmt.Sprintf("%v", value) 转换为字符串之后处理 func Encode(vs ...interface{}) []byte { - buf := new(bytes.Buffer) - for i := 0; i < len(vs); i++ { - switch value := vs[i].(type) { - case int: buf.Write(EncodeInt(value)) - case int8: buf.Write(EncodeInt8(value)) - case int16: buf.Write(EncodeInt16(value)) - case int32: buf.Write(EncodeInt32(value)) - case int64: buf.Write(EncodeInt64(value)) - case uint: buf.Write(EncodeUint(value)) - case uint8: buf.Write(EncodeUint8(value)) - case uint16: buf.Write(EncodeUint16(value)) - case uint32: buf.Write(EncodeUint32(value)) - case uint64: buf.Write(EncodeUint64(value)) - case bool: buf.Write(EncodeBool(value)) - case string: buf.Write(EncodeString(value)) - case []byte: buf.Write(value) - case float32: buf.Write(EncodeFloat32(value)) - case float64: buf.Write(EncodeFloat64(value)) - default: - if err := binary.Write(buf, binary.LittleEndian, value); err != nil { - buf.Write(EncodeString(fmt.Sprintf("%v", value))) - } - } - } - return buf.Bytes() + buf := new(bytes.Buffer) + for i := 0; i < len(vs); i++ { + if vs[i] == nil { + return buf.Bytes() + } + switch value := vs[i].(type) { + case int: + buf.Write(EncodeInt(value)) + case int8: + buf.Write(EncodeInt8(value)) + case int16: + buf.Write(EncodeInt16(value)) + case int32: + buf.Write(EncodeInt32(value)) + case int64: + buf.Write(EncodeInt64(value)) + case uint: + buf.Write(EncodeUint(value)) + case uint8: + buf.Write(EncodeUint8(value)) + case uint16: + buf.Write(EncodeUint16(value)) + case uint32: + buf.Write(EncodeUint32(value)) + case uint64: + buf.Write(EncodeUint64(value)) + case bool: + buf.Write(EncodeBool(value)) + case string: + buf.Write(EncodeString(value)) + case []byte: + buf.Write(value) + case float32: + buf.Write(EncodeFloat32(value)) + case float64: + buf.Write(EncodeFloat64(value)) + default: + if err := binary.Write(buf, binary.LittleEndian, value); err != nil { + buf.Write(EncodeString(fmt.Sprintf("%v", value))) + } + + } + } + return buf.Bytes() } // 将变量转换为二进制[]byte,并指定固定的[]byte长度返回,长度单位为字节(byte); // 如果转换的二进制长度超过指定长度,那么进行截断处理 func EncodeByLength(length int, vs ...interface{}) []byte { - b := Encode(vs...) - if len(b) < length { - b = append(b, make([]byte, length - len(b))...) - } else if len(b) > length { - b = b[0 : length] - } - return b + b := Encode(vs...) + if len(b) < length { + b = append(b, make([]byte, length-len(b))...) + } else if len(b) > length { + b = b[0:length] + } + return b } // 整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,以便确定解析的[]byte长度, // 例如:int8/16/32/64、uint8/16/32/64、float32/64等等 func Decode(b []byte, vs ...interface{}) error { - buf := bytes.NewBuffer(b) - for i := 0; i < len(vs); i++ { - err := binary.Read(buf, binary.LittleEndian, vs[i]) - if err != nil { - return err - } - } - return nil + buf := bytes.NewBuffer(b) + for i := 0; i < len(vs); i++ { + err := binary.Read(buf, binary.LittleEndian, vs[i]) + if err != nil { + return err + } + } + return nil } func EncodeString(s string) []byte { - return []byte(s) + return []byte(s) } func DecodeToString(b []byte) string { - return string(b) + return string(b) } func EncodeBool(b bool) []byte { - if b == true { - return []byte{1} - } else { - return []byte{0} - } + if b == true { + return []byte{1} + } else { + return []byte{0} + } } // 自动识别int类型长度,转换为[]byte func EncodeInt(i int) []byte { - if i <= math.MaxInt8 { - return EncodeInt8(int8(i)) - } else if i <= math.MaxInt16 { - return EncodeInt16(int16(i)) - } else if i <= math.MaxInt32 { - return EncodeInt32(int32(i)) - } else { - return EncodeInt64(int64(i)) - } + if i <= math.MaxInt8 { + return EncodeInt8(int8(i)) + } else if i <= math.MaxInt16 { + return EncodeInt16(int16(i)) + } else if i <= math.MaxInt32 { + return EncodeInt32(int32(i)) + } else { + return EncodeInt64(int64(i)) + } } // 自动识别uint类型长度,转换为[]byte func EncodeUint(i uint) []byte { - if i <= math.MaxUint8 { - return EncodeUint8(uint8(i)) - } else if i <= math.MaxUint16 { - return EncodeUint16(uint16(i)) - } else if i <= math.MaxUint32 { - return EncodeUint32(uint32(i)) - } else { - return EncodeUint64(uint64(i)) - } + if i <= math.MaxUint8 { + return EncodeUint8(uint8(i)) + } else if i <= math.MaxUint16 { + return EncodeUint16(uint16(i)) + } else if i <= math.MaxUint32 { + return EncodeUint32(uint32(i)) + } else { + return EncodeUint64(uint64(i)) + } } func EncodeInt8(i int8) []byte { - return []byte{byte(i)} + return []byte{byte(i)} } func EncodeUint8(i uint8) []byte { - return []byte{byte(i)} + return []byte{byte(i)} } func EncodeInt16(i int16) []byte { - bytes := make([]byte, 2) - binary.LittleEndian.PutUint16(bytes, uint16(i)) - return bytes + bytes := make([]byte, 2) + binary.LittleEndian.PutUint16(bytes, uint16(i)) + return bytes } func EncodeUint16(i uint16) []byte { - bytes := make([]byte, 2) - binary.LittleEndian.PutUint16(bytes, i) - return bytes + bytes := make([]byte, 2) + binary.LittleEndian.PutUint16(bytes, i) + return bytes } func EncodeInt32(i int32) []byte { - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, uint32(i)) - return bytes + bytes := make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, uint32(i)) + return bytes } func EncodeUint32(i uint32) []byte { - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, i) - return bytes + bytes := make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, i) + return bytes } func EncodeInt64(i int64) []byte { - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, uint64(i)) - return bytes + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, uint64(i)) + return bytes } func EncodeUint64(i uint64) []byte { - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, i) - return bytes + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, i) + return bytes } func EncodeFloat32(f float32) []byte { - bits := math.Float32bits(f) - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, bits) - return bytes + bits := math.Float32bits(f) + bytes := make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, bits) + return bytes } func EncodeFloat64(f float64) []byte { - bits := math.Float64bits(f) - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, bits) - return bytes + bits := math.Float64bits(f) + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, bits) + return bytes } // 当b位数不够时,进行高位补0 func fillUpSize(b []byte, l int) []byte { - if len(b) >= l { - return b - } - c := make([]byte, 0) - c = append(c, b...) - for i := 0; i < l - len(b); i++ { - c = append(c, 0x00) - } - return c + if len(b) >= l { + return b + } + c := make([]byte, 0) + c = append(c, b...) + for i := 0; i < l-len(b); i++ { + c = append(c, 0x00) + } + return c } // 将二进制解析为int类型,根据[]byte的长度进行自动转换. // 注意内部使用的是uint*,使用int会造成位丢失。 func DecodeToInt(b []byte) int { - if len(b) < 2 { - return int(DecodeToUint8(b)) - } else if len(b) < 3 { - return int(DecodeToUint16(b)) - } else if len(b) < 5 { - return int(DecodeToUint32(b)) - } else { - return int(DecodeToUint64(b)) - } + if len(b) < 2 { + return int(DecodeToUint8(b)) + } else if len(b) < 3 { + return int(DecodeToUint16(b)) + } else if len(b) < 5 { + return int(DecodeToUint32(b)) + } else { + return int(DecodeToUint64(b)) + } } // 将二进制解析为uint类型,根据[]byte的长度进行自动转换 func DecodeToUint(b []byte) uint { - if len(b) < 2 { - return uint(DecodeToUint8(b)) - } else if len(b) < 3 { - return uint(DecodeToUint16(b)) - } else if len(b) < 5 { - return uint(DecodeToUint32(b)) - } else { - return uint(DecodeToUint64(b)) - } + if len(b) < 2 { + return uint(DecodeToUint8(b)) + } else if len(b) < 3 { + return uint(DecodeToUint16(b)) + } else if len(b) < 5 { + return uint(DecodeToUint32(b)) + } else { + return uint(DecodeToUint64(b)) + } } // 将二进制解析为bool类型,识别标准是判断二进制中数值是否都为0,或者为空 func DecodeToBool(b []byte) bool { - if len(b) == 0 { - return false - } - if bytes.Compare(b, make([]byte, len(b))) == 0 { - return false - } - return true + if len(b) == 0 { + return false + } + if bytes.Compare(b, make([]byte, len(b))) == 0 { + return false + } + return true } func DecodeToInt8(b []byte) int8 { - return int8(b[0]) + return int8(b[0]) } func DecodeToUint8(b []byte) uint8 { - return uint8(b[0]) + return uint8(b[0]) } func DecodeToInt16(b []byte) int16 { - return int16(binary.LittleEndian.Uint16(fillUpSize(b, 2))) + return int16(binary.LittleEndian.Uint16(fillUpSize(b, 2))) } func DecodeToUint16(b []byte) uint16 { - return binary.LittleEndian.Uint16(fillUpSize(b, 2)) + return binary.LittleEndian.Uint16(fillUpSize(b, 2)) } func DecodeToInt32(b []byte) int32 { - return int32(binary.LittleEndian.Uint32(fillUpSize(b, 4))) + return int32(binary.LittleEndian.Uint32(fillUpSize(b, 4))) } func DecodeToUint32(b []byte) uint32 { - return binary.LittleEndian.Uint32(fillUpSize(b, 4)) + return binary.LittleEndian.Uint32(fillUpSize(b, 4)) } func DecodeToInt64(b []byte) int64 { - return int64(binary.LittleEndian.Uint64(fillUpSize(b, 8))) + return int64(binary.LittleEndian.Uint64(fillUpSize(b, 8))) } func DecodeToUint64(b []byte) uint64 { - return binary.LittleEndian.Uint64(fillUpSize(b, 8)) + return binary.LittleEndian.Uint64(fillUpSize(b, 8)) } func DecodeToFloat32(b []byte) float32 { - return math.Float32frombits(binary.LittleEndian.Uint32(fillUpSize(b, 4))) + return math.Float32frombits(binary.LittleEndian.Uint32(fillUpSize(b, 4))) } func DecodeToFloat64(b []byte) float64 { - return math.Float64frombits(binary.LittleEndian.Uint64(fillUpSize(b, 8))) + return math.Float64frombits(binary.LittleEndian.Uint64(fillUpSize(b, 8))) } // 默认编码 func EncodeBits(bits []Bit, i int, l int) []Bit { - return EncodeBitsWithUint(bits, uint(i), l) + return EncodeBitsWithUint(bits, uint(i), l) } // 将ui按位合并到bits数组中,并占length长度位(注意:uis数组中存放的是二进制的0|1数字) func EncodeBitsWithUint(bits []Bit, ui uint, l int) []Bit { - a := make([]Bit, l) - for i := l - 1; i >= 0; i-- { - a[i] = Bit(ui & 1) - ui >>= 1 - } - if bits != nil { - return append(bits, a...) - } else { - return a - } + a := make([]Bit, l) + for i := l - 1; i >= 0; i-- { + a[i] = Bit(ui & 1) + ui >>= 1 + } + if bits != nil { + return append(bits, a...) + } else { + return a + } } + // 将bits转换为[]byte,从左至右进行编码,不足1 byte按0往末尾补充 func EncodeBitsToBytes(bits []Bit) []byte { - if len(bits)%8 != 0 { - for i := 0; i < len(bits)%8; i++ { - bits = append(bits, 0) - } - } - b := make([]byte, 0) - for i := 0; i < len(bits); i += 8 { - b = append(b, byte(DecodeBitsToUint(bits[i : i + 8]))) - } - return b + if len(bits)%8 != 0 { + for i := 0; i < len(bits)%8; i++ { + bits = append(bits, 0) + } + } + b := make([]byte, 0) + for i := 0; i < len(bits); i += 8 { + b = append(b, byte(DecodeBitsToUint(bits[i:i+8]))) + } + return b } // 解析为int func DecodeBits(bits []Bit) int { - v := int(0) - for _, i := range bits { - v = v << 1 | int(i) - } - return v + v := int(0) + for _, i := range bits { + v = v<<1 | int(i) + } + return v } // 解析为uint func DecodeBitsToUint(bits []Bit) uint { - v := uint(0) - for _, i := range bits { - v = v << 1 | uint(i) - } - return v + v := uint(0) + for _, i := range bits { + v = v<<1 | uint(i) + } + return v } // 解析[]byte为字位数组[]uint8 func DecodeBytesToBits(bs []byte) []Bit { - bits := make([]Bit, 0) - for _, b := range bs { - bits = EncodeBitsWithUint(bits, uint(b), 8) - } - return bits -} \ No newline at end of file + bits := make([]Bit, 0) + for _, b := range bs { + bits = EncodeBitsWithUint(bits, uint(b), 8) + } + return bits +} From fd63a2209b8d27fb8e39bcbd91287932e9c84301 Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Thu, 4 Apr 2019 23:31:17 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/encoding/gbinary/gbinary.go | 72 ++++++++++++++--------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/g/encoding/gbinary/gbinary.go b/g/encoding/gbinary/gbinary.go index 532c38065..a7ad3c301 100644 --- a/g/encoding/gbinary/gbinary.go +++ b/g/encoding/gbinary/gbinary.go @@ -8,10 +8,10 @@ package gbinary import ( - "bytes" - "encoding/binary" "fmt" "math" + "bytes" + "encoding/binary" ) // 二进制位(0|1) @@ -25,42 +25,27 @@ func Encode(vs ...interface{}) []byte { if vs[i] == nil { return buf.Bytes() } + switch value := vs[i].(type) { - case int: - buf.Write(EncodeInt(value)) - case int8: - buf.Write(EncodeInt8(value)) - case int16: - buf.Write(EncodeInt16(value)) - case int32: - buf.Write(EncodeInt32(value)) - case int64: - buf.Write(EncodeInt64(value)) - case uint: - buf.Write(EncodeUint(value)) - case uint8: - buf.Write(EncodeUint8(value)) - case uint16: - buf.Write(EncodeUint16(value)) - case uint32: - buf.Write(EncodeUint32(value)) - case uint64: - buf.Write(EncodeUint64(value)) - case bool: - buf.Write(EncodeBool(value)) - case string: - buf.Write(EncodeString(value)) - case []byte: - buf.Write(value) - case float32: - buf.Write(EncodeFloat32(value)) - case float64: - buf.Write(EncodeFloat64(value)) + case int: buf.Write(EncodeInt(value)) + case int8: buf.Write(EncodeInt8(value)) + case int16: buf.Write(EncodeInt16(value)) + case int32: buf.Write(EncodeInt32(value)) + case int64: buf.Write(EncodeInt64(value)) + case uint: buf.Write(EncodeUint(value)) + case uint8: buf.Write(EncodeUint8(value)) + case uint16: buf.Write(EncodeUint16(value)) + case uint32: buf.Write(EncodeUint32(value)) + case uint64: buf.Write(EncodeUint64(value)) + case bool: buf.Write(EncodeBool(value)) + case string: buf.Write(EncodeString(value)) + case []byte: buf.Write(value) + case float32: buf.Write(EncodeFloat32(value)) + case float64: buf.Write(EncodeFloat64(value)) default: if err := binary.Write(buf, binary.LittleEndian, value); err != nil { buf.Write(EncodeString(fmt.Sprintf("%v", value))) } - } } return buf.Bytes() @@ -71,9 +56,9 @@ func Encode(vs ...interface{}) []byte { func EncodeByLength(length int, vs ...interface{}) []byte { b := Encode(vs...) if len(b) < length { - b = append(b, make([]byte, length-len(b))...) + b = append(b, make([]byte, length - len(b))...) } else if len(b) > length { - b = b[0:length] + b = b[0 : length] } return b } @@ -178,14 +163,14 @@ func EncodeUint64(i uint64) []byte { } func EncodeFloat32(f float32) []byte { - bits := math.Float32bits(f) + bits := math.Float32bits(f) bytes := make([]byte, 4) binary.LittleEndian.PutUint32(bytes, bits) return bytes } func EncodeFloat64(f float64) []byte { - bits := math.Float64bits(f) + bits := math.Float64bits(f) bytes := make([]byte, 8) binary.LittleEndian.PutUint64(bytes, bits) return bytes @@ -197,8 +182,8 @@ func fillUpSize(b []byte, l int) []byte { return b } c := make([]byte, 0) - c = append(c, b...) - for i := 0; i < l-len(b); i++ { + c = append(c, b...) + for i := 0; i < l - len(b); i++ { c = append(c, 0x00) } return c @@ -300,7 +285,6 @@ func EncodeBitsWithUint(bits []Bit, ui uint, l int) []Bit { return a } } - // 将bits转换为[]byte,从左至右进行编码,不足1 byte按0往末尾补充 func EncodeBitsToBytes(bits []Bit) []byte { if len(bits)%8 != 0 { @@ -310,7 +294,7 @@ func EncodeBitsToBytes(bits []Bit) []byte { } b := make([]byte, 0) for i := 0; i < len(bits); i += 8 { - b = append(b, byte(DecodeBitsToUint(bits[i:i+8]))) + b = append(b, byte(DecodeBitsToUint(bits[i : i + 8]))) } return b } @@ -319,7 +303,7 @@ func EncodeBitsToBytes(bits []Bit) []byte { func DecodeBits(bits []Bit) int { v := int(0) for _, i := range bits { - v = v<<1 | int(i) + v = v << 1 | int(i) } return v } @@ -328,7 +312,7 @@ func DecodeBits(bits []Bit) int { func DecodeBitsToUint(bits []Bit) uint { v := uint(0) for _, i := range bits { - v = v<<1 | uint(i) + v = v << 1 | uint(i) } return v } @@ -340,4 +324,4 @@ func DecodeBytesToBits(bs []byte) []Bit { bits = EncodeBitsWithUint(bits, uint(b), 8) } return bits -} +} \ No newline at end of file From 43886511b9c77f3c8da8f78c01ec95a0b5b5effc Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Tue, 9 Apr 2019 12:28:21 +0800 Subject: [PATCH 4/8] add unit test --- g/encoding/gbinary/gbinary_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g/encoding/gbinary/gbinary_test.go b/g/encoding/gbinary/gbinary_test.go index 2cb64a848..cf85fc3c9 100644 --- a/g/encoding/gbinary/gbinary_test.go +++ b/g/encoding/gbinary/gbinary_test.go @@ -14,7 +14,7 @@ import ( ) var testData = map[string]interface{}{ - "nil": nil, + //"nil": nil, "int": int(123), "int8": int8(-99), "int8.max": math.MaxInt8, From b3d5fc149ed0d8b88e9f4dcb664bbbc698d22cce Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Tue, 9 Apr 2019 17:27:11 +0800 Subject: [PATCH 5/8] add unit test --- g/encoding/gbinary/gbinary_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/g/encoding/gbinary/gbinary_test.go b/g/encoding/gbinary/gbinary_test.go index cf85fc3c9..7e875a9b4 100644 --- a/g/encoding/gbinary/gbinary_test.go +++ b/g/encoding/gbinary/gbinary_test.go @@ -23,16 +23,13 @@ var testData = map[string]interface{}{ "int32": int32(-199), "int32.max": math.MaxInt32, "int64": int64(123), - "int64.max": math.MaxInt64, "uint": uint(123), "uint8": uint8(123), "uint8.max": math.MaxUint8, "uint16": uint16(9999), "uint16.max": math.MaxUint16, "uint32": uint32(123), - "uint32.max": math.MaxUint32, "uint64": uint64(123), - "uint64.max": math.MaxUint32 + 1, "bool.true": true, "bool.false": false, "string": "hehe haha", @@ -40,7 +37,6 @@ var testData = map[string]interface{}{ "float32": float32(123.456), "float32.max": math.MaxFloat32, "float64": float64(123.456), - "float64.max": math.MaxFloat64, } func TestEncodeAndDecode(t *testing.T) { From 053a3c1a53f5d8b9de11f6f57975d612f6c85a93 Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Tue, 9 Apr 2019 19:12:48 +0800 Subject: [PATCH 6/8] add unit test --- g/encoding/gbase64/gbase64_test.go | 51 ++++++++++++++++++++++++++ g/encoding/gcompress/gcompress_test.go | 28 ++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 g/encoding/gbase64/gbase64_test.go create mode 100644 g/encoding/gcompress/gcompress_test.go diff --git a/g/encoding/gbase64/gbase64_test.go b/g/encoding/gbase64/gbase64_test.go new file mode 100644 index 000000000..1772db5f5 --- /dev/null +++ b/g/encoding/gbase64/gbase64_test.go @@ -0,0 +1,51 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package gbase64_test + +import ( + "github.com/gogf/gf/g/encoding/gbase64" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +type testpair struct { + decoded, encoded string +} + +var pairs = []testpair{ + // RFC 3548 examples + {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+"}, + {"\x14\xfb\x9c\x03\xd9", "FPucA9k="}, + {"\x14\xfb\x9c\x03", "FPucAw=="}, + + // RFC 4648 examples + {"", ""}, + {"f", "Zg=="}, + {"fo", "Zm8="}, + {"foo", "Zm9v"}, + {"foob", "Zm9vYg=="}, + {"fooba", "Zm9vYmE="}, + {"foobar", "Zm9vYmFy"}, + + // Wikipedia examples + {"sure.", "c3VyZS4="}, + {"sure", "c3VyZQ=="}, + {"sur", "c3Vy"}, + {"su", "c3U="}, + {"leasure.", "bGVhc3VyZS4="}, + {"easure.", "ZWFzdXJlLg=="}, + {"asure.", "YXN1cmUu"}, + {"sure.", "c3VyZS4="}, +} + +func TestBase64(t *testing.T) { + for k := range pairs{ + gtest.Assert(gbase64.Encode(pairs[k].decoded), pairs[k].encoded) + + e, _ := gbase64.Decode(pairs[k].encoded) + gtest.Assert(e, pairs[k].decoded) + } +} diff --git a/g/encoding/gcompress/gcompress_test.go b/g/encoding/gcompress/gcompress_test.go new file mode 100644 index 000000000..17829f8af --- /dev/null +++ b/g/encoding/gcompress/gcompress_test.go @@ -0,0 +1,28 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package gcompress_test + +import ( + "github.com/gogf/gf/g/util/grand" + "github.com/gogf/gf/g/encoding/gcompress" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +var times = 10 +var length = 2000 + +func TestCompress(t *testing.T) { + for i := 0; i < times; i++ { + src := grand.RandStr(length + i * 10) + zlibVal := gcompress.Zlib([]byte(src)) + dst := gcompress.UnZlib(zlibVal) + gtest.Assert(dst, []byte(src)) + + dst1 := gcompress.UnGzip(gcompress.Gzip([]byte(src))) + gtest.Assert(dst1, []byte(src)) + } +} From 0fc825dac1375bd1d305243014b90c050f4d791f Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Thu, 18 Apr 2019 12:34:01 +0800 Subject: [PATCH 7/8] add gcompress packge unit test --- g/encoding/gcompress/gcompress_test.go | 38 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/g/encoding/gcompress/gcompress_test.go b/g/encoding/gcompress/gcompress_test.go index 17829f8af..df1bbb6f3 100644 --- a/g/encoding/gcompress/gcompress_test.go +++ b/g/encoding/gcompress/gcompress_test.go @@ -6,23 +6,37 @@ package gcompress_test import ( - "github.com/gogf/gf/g/util/grand" "github.com/gogf/gf/g/encoding/gcompress" "github.com/gogf/gf/g/test/gtest" "testing" ) -var times = 10 -var length = 2000 +func TestZlib(t *testing.T) { + gtest.Case(t, func() { + src := "hello, world\n" + dst := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147} + gtest.Assert(gcompress.Zlib([]byte(src)), dst) -func TestCompress(t *testing.T) { - for i := 0; i < times; i++ { - src := grand.RandStr(length + i * 10) - zlibVal := gcompress.Zlib([]byte(src)) - dst := gcompress.UnZlib(zlibVal) - gtest.Assert(dst, []byte(src)) + gtest.Assert(gcompress.UnZlib(dst), []byte(src)) + }) - dst1 := gcompress.UnGzip(gcompress.Gzip([]byte(src))) - gtest.Assert(dst1, []byte(src)) - } +} + +func TestGzip(t *testing.T) { + src := "Hello World!!" + + gzip := []byte{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf2, 0x48, 0xcd, 0xc9, 0xc9, + 0x57, 0x08, 0xcf, 0x2f, 0xca, + 0x49, 0x51, 0x54, 0x04, 0x04, + 0x00, 0x00, 0xff, 0xff, 0x9d, + 0x24, 0xa8, 0xd1, 0x0d, 0x00, + 0x00, 0x00, + } + + gtest.Assert(gcompress.Gzip([]byte(src)), gzip) + + gtest.Assert(gcompress.UnGzip(gzip), []byte(src)) } From 07ab1d60e81abfcb7fa1af09a03112d3a969eede Mon Sep 17 00:00:00 2001 From: wenzi1 Date: Fri, 19 Apr 2019 17:04:43 +0800 Subject: [PATCH 8/8] add encoding package unit test --- g/encoding/ghtml/ghtml_test.go | 32 ++++++++ g/encoding/gtoml/gtoml_test.go | 142 ++++++++++++++++++++++++++++++++ g/encoding/gurl/url_test.go | 92 +++++++++++++++++++++ g/encoding/gyaml/gyaml_test.go | 143 +++++++++++++++++++++++++++++++++ 4 files changed, 409 insertions(+) create mode 100644 g/encoding/ghtml/ghtml_test.go create mode 100644 g/encoding/gtoml/gtoml_test.go create mode 100644 g/encoding/gurl/url_test.go create mode 100644 g/encoding/gyaml/gyaml_test.go diff --git a/g/encoding/ghtml/ghtml_test.go b/g/encoding/ghtml/ghtml_test.go new file mode 100644 index 000000000..f88f5d0a1 --- /dev/null +++ b/g/encoding/ghtml/ghtml_test.go @@ -0,0 +1,32 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package ghtml_test + +import ( + "github.com/gogf/gf/g/encoding/ghtml" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func TestStripTags(t *testing.T) { + src := `

Test paragraph.

Other text` + dst := `Test paragraph. Other text` + gtest.Assert(ghtml.StripTags(src), dst) +} + +func TestEntities(t *testing.T) { + src := `A 'quote' "is" bold` + dst := `A 'quote' "is" <b>bold</b>` + gtest.Assert(ghtml.Entities(src), dst) + gtest.Assert(ghtml.EntitiesDecode(dst), src) +} + +func TestSpecialChars(t *testing.T) { + src := `A 'quote' "is" bold` + dst := `A 'quote' "is" <b>bold</b>` + gtest.Assert(ghtml.SpecialChars(src), dst) + gtest.Assert(ghtml.SpecialCharsDecode(dst), src) +} diff --git a/g/encoding/gtoml/gtoml_test.go b/g/encoding/gtoml/gtoml_test.go new file mode 100644 index 000000000..4399c78c0 --- /dev/null +++ b/g/encoding/gtoml/gtoml_test.go @@ -0,0 +1,142 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package gtoml_test + +import ( + "github.com/gogf/gf/g/encoding/gparser" + "github.com/gogf/gf/g/encoding/gtoml" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +var tomlStr string = ` +# 模板引擎目录 +viewpath = "/home/www/templates/" +# MySQL数据库配置 +[redis] + disk = "127.0.0.1:6379,0" + cache = "127.0.0.1:6379,1" +` + +var tomlErr string = ` +# 模板引擎目录 +viewpath = "/home/www/templates/" +# MySQL数据库配置 +[redis] +dd = 11 +[redis] + disk = "127.0.0.1:6379,0" + cache = "127.0.0.1:6379,1" +` + +func TestEncode(t *testing.T) { + gtest.Case(t, func() { + m := make(map[string]string) + m["toml"] = tomlStr + res, err := gtoml.Encode(m) + if err != nil { + t.Errorf("encode failed. %v", err) + return + } + + p, err := gparser.LoadContent(res) + if err != nil { + t.Errorf("parser failed. %v", err) + return + } + + gtest.Assert(p.GetString("toml"), tomlStr) + }) + + gtest.Case(t, func() { + _, err := gtoml.Encode(tomlErr) + if err == nil { + t.Errorf("encode should be failed. %v", err) + return + } + }) +} + +func TestDecode(t *testing.T) { + gtest.Case(t, func() { + m := make(map[string]string) + m["toml"] = tomlStr + res, err := gtoml.Encode(m) + if err != nil { + t.Errorf("encode failed. %v", err) + return + } + + decodeStr, err := gtoml.Decode(res) + if err != nil { + t.Errorf("decode failed. %v", err) + return + } + + gtest.Assert(decodeStr.(map[string]interface{})["toml"], tomlStr) + + decodeStr1 := make(map[string]interface{}) + err = gtoml.DecodeTo(res, &decodeStr1) + if err != nil { + t.Errorf("decodeTo failed. %v", err) + return + } + gtest.Assert(decodeStr1["toml"], tomlStr) + }) + + gtest.Case(t, func() { + _, err := gtoml.Decode([]byte(tomlErr)) + if err == nil { + t.Errorf("decode failed. %v", err) + return + } + + decodeStr1 := make(map[string]interface{}) + err = gtoml.DecodeTo([]byte(tomlErr), &decodeStr1) + if err == nil { + t.Errorf("decodeTo failed. %v", err) + return + } + }) +} + +func TestToJson(t *testing.T) { + gtest.Case(t, func() { + m := make(map[string]string) + m["toml"] = tomlStr + res, err := gtoml.Encode(m) + if err != nil { + t.Errorf("encode failed. %v", err) + return + } + + jsonToml, err := gtoml.ToJson(res) + if err != nil { + t.Errorf("ToJson failed. %v", err) + return + } + + p, err := gparser.LoadContent(res) + if err != nil { + t.Errorf("parser failed. %v", err) + return + } + expectJson, err := p.ToJson() + if err != nil { + t.Errorf("parser ToJson failed. %v", err) + return + } + gtest.Assert(jsonToml, expectJson) + }) + + gtest.Case(t, func() { + _, err := gtoml.ToJson([]byte(tomlErr)) + if err == nil { + t.Errorf("ToJson failed. %v", err) + return + } + }) +} diff --git a/g/encoding/gurl/url_test.go b/g/encoding/gurl/url_test.go new file mode 100644 index 000000000..65205e753 --- /dev/null +++ b/g/encoding/gurl/url_test.go @@ -0,0 +1,92 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package gurl_test + +import ( + "github.com/gogf/gf/g/encoding/gurl" + "github.com/gogf/gf/g/test/gtest" + "net/url" + "testing" +) + +var urlStr string = `https://golang.org/x/crypto?go-get=1 +` +var urlEncode string = `https%3A%2F%2Fgolang.org%2Fx%2Fcrypto%3Fgo-get%3D1+%2B` +var rawUrlEncode string = `https%3A%2F%2Fgolang.org%2Fx%2Fcrypto%3Fgo-get%3D1%20%2B` + +func TestEncodeAndDecode(t *testing.T) { + gtest.Case(t, func() { + gtest.Assert(gurl.Encode(urlStr), urlEncode) + + res, err := gurl.Decode(urlEncode) + if err != nil { + t.Errorf("decode failed. %v", err) + return + } + gtest.Assert(res, urlStr) + }) +} + +func TestRowEncodeAndDecode(t *testing.T) { + gtest.Case(t, func() { + gtest.Assert(gurl.RawEncode(urlStr), rawUrlEncode) + + res, err := gurl.RawDecode(rawUrlEncode) + if err != nil { + t.Errorf("decode failed. %v", err) + return + } + gtest.Assert(res, urlStr) + }) +} + +func TestBuildQuery(t *testing.T) { + src := url.Values{ + "a": {"a2", "a1"}, + "b": {"b2", "b1"}, + "c": {"c1", "c2"}, + } + expect := "a=a2&a=a1&b=b2&b=b1&c=c1&c=c2" + + gtest.Assert(gurl.BuildQuery(src), expect) +} + +func TestParseURL(t *testing.T) { + src := `http://username:password@hostname:9090/path?arg=value#anchor` + expect := map[string]string{ + "scheme": "http", + "host": "hostname", + "port": "9090", + "user": "username", + "pass": "password", + "path": "/path", + "query": "arg=value", + "fragment": "anchor", + } + + gtest.Case(t, func() { + component := 0 + for k, v := range []string{"all", "scheme", "host", "port", "user", "pass", "path", "query", "fragment"} { + if v == "all" { + component = -1 + } else { + component = 1 << (uint(k - 1)) + } + + res, err := gurl.ParseURL(src, component) + if err != nil { + t.Errorf("ParseURL failed. component:%v, err:%v", component, err) + return + } + + if v == "all" { + gtest.Assert(res, expect) + } else { + gtest.Assert(res[v], expect[v]) + } + + } + }) +} diff --git a/g/encoding/gyaml/gyaml_test.go b/g/encoding/gyaml/gyaml_test.go new file mode 100644 index 000000000..f5750d56a --- /dev/null +++ b/g/encoding/gyaml/gyaml_test.go @@ -0,0 +1,143 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package gyaml_test + +import ( + "github.com/gogf/gf/g/encoding/gparser" + "github.com/gogf/gf/g/encoding/gyaml" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +var yamlStr string = ` +#即表示url属性值; +url: http://www.wolfcode.cn +#即表示server.host属性的值; +server: + host: http://www.wolfcode.cn +#数组,即表示server为[a,b,c] +server: + - 120.168.117.21 + - 120.168.117.22 + - 120.168.117.23 +#常量 +pi: 3.14 #定义一个数值3.14 +hasChild: true #定义一个boolean值 +name: '你好YAML' #定义一个字符串 +` + +var yamlErr string = ` +# 模板引擎目录 +viewpath = "/home/www/templates/" +# MySQL数据库配置 +[redis] +dd = 11 +[redis] + disk = "127.0.0.1:6379,0" + cache = "127.0.0.1:6379,1" +` + +func TestEncode(t *testing.T) { + gtest.Case(t, func() { + m := make(map[string]string) + m["yaml"] = yamlStr + res, err := gyaml.Encode(m) + if err != nil { + t.Errorf("encode failed. %v", err) + return + } + + p, err := gparser.LoadContent(res) + if err != nil { + t.Errorf("parser failed. %v", err) + return + } + + gtest.Assert(p.GetString("yaml"), yamlStr) + }) + +} + +func TestDecode(t *testing.T) { + gtest.Case(t, func() { + m := make(map[string]string) + m["yaml"] = yamlStr + res, err := gyaml.Encode(m) + if err != nil { + t.Errorf("encode failed. %v", err) + return + } + + decodeStr, err := gyaml.Decode(res) + if err != nil { + t.Errorf("decode failed. %v", err) + return + } + + gtest.Assert(decodeStr.(map[string]interface{})["yaml"], yamlStr) + + decodeStr1 := make(map[string]interface{}) + err = gyaml.DecodeTo(res, &decodeStr1) + if err != nil { + t.Errorf("decodeTo failed. %v", err) + return + } + gtest.Assert(decodeStr1["yaml"], yamlStr) + }) + + gtest.Case(t, func() { + _, err := gyaml.Decode([]byte(yamlErr)) + if err == nil { + t.Errorf("decode failed. %v", err) + return + } + + decodeStr1 := make(map[string]interface{}) + err = gyaml.DecodeTo([]byte(yamlErr), &decodeStr1) + if err == nil { + t.Errorf("decodeTo failed. %v", err) + return + } + }) +} + +func TestToJson(t *testing.T) { + gtest.Case(t, func() { + m := make(map[string]string) + m["yaml"] = yamlStr + res, err := gyaml.Encode(m) + if err != nil { + t.Errorf("encode failed. %v", err) + return + } + + jsonyaml, err := gyaml.ToJson(res) + if err != nil { + t.Errorf("ToJson failed. %v", err) + return + } + + p, err := gparser.LoadContent(res) + if err != nil { + t.Errorf("parser failed. %v", err) + return + } + expectJson, err := p.ToJson() + if err != nil { + t.Errorf("parser ToJson failed. %v", err) + return + } + gtest.Assert(jsonyaml, expectJson) + }) + + gtest.Case(t, func() { + _, err := gyaml.ToJson([]byte(yamlErr)) + if err == nil { + t.Errorf("ToJson failed. %v", err) + return + } + }) +}