158 lines
4.6 KiB
Go
158 lines
4.6 KiB
Go
|
package utils
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
|
||
|
. "github.com/onsi/ginkgo"
|
||
|
. "github.com/onsi/gomega"
|
||
|
)
|
||
|
|
||
|
var _ = Describe("Varint encoding / decoding", func() {
|
||
|
Context("decoding", func() {
|
||
|
It("reads a 1 byte number", func() {
|
||
|
b := bytes.NewReader([]byte{25}) // 00011001
|
||
|
val, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(val).To(Equal(uint64(25)))
|
||
|
Expect(b.Len()).To(BeZero())
|
||
|
})
|
||
|
|
||
|
It("reads a number that is encoded too long", func() {
|
||
|
b := bytes.NewReader([]byte{0x40, 0x25}) // first byte: 01000000
|
||
|
val, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(val).To(Equal(uint64(37)))
|
||
|
Expect(b.Len()).To(BeZero())
|
||
|
})
|
||
|
|
||
|
It("reads a 2 byte number", func() {
|
||
|
b := bytes.NewReader([]byte{0x7b, 0xbd}) // first byte: 01111011
|
||
|
val, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(val).To(Equal(uint64(15293)))
|
||
|
Expect(b.Len()).To(BeZero())
|
||
|
})
|
||
|
|
||
|
It("reads a 4 byte number", func() {
|
||
|
b := bytes.NewReader([]byte{0x9d, 0x7f, 0x3e, 0x7d}) // first byte: 10011011
|
||
|
val, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(val).To(Equal(uint64(494878333)))
|
||
|
Expect(b.Len()).To(BeZero())
|
||
|
})
|
||
|
|
||
|
It("reads an 8 byte number", func() {
|
||
|
b := bytes.NewReader([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c}) // first byte: 10000010
|
||
|
val, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(val).To(Equal(uint64(151288809941952652)))
|
||
|
Expect(b.Len()).To(BeZero())
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("encoding", func() {
|
||
|
It("writes a 1 byte number", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, 37)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0x25}))
|
||
|
})
|
||
|
|
||
|
It("writes the maximum 1 byte number in 1 byte", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt1)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0x3f /* 00111111 */}))
|
||
|
})
|
||
|
|
||
|
It("writes the minimum 2 byte number in 2 bytes", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt1+1)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0x40, maxVarInt1 + 1}))
|
||
|
})
|
||
|
|
||
|
It("writes a 2 byte number", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, 15293)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0x7b, 0xbd}))
|
||
|
})
|
||
|
|
||
|
It("writes the maximum 2 byte number in 2 bytes", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt2)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0x7f /* 01111111 */, 0xff}))
|
||
|
})
|
||
|
|
||
|
It("writes the minimum 4 byte number in 4 bytes", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt2+1)
|
||
|
Expect(b.Len()).To(Equal(4))
|
||
|
num, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(num).To(Equal(uint64(maxVarInt2 + 1)))
|
||
|
})
|
||
|
|
||
|
It("writes a 4 byte number", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, 494878333)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0x9d, 0x7f, 0x3e, 0x7d}))
|
||
|
})
|
||
|
|
||
|
It("writes the maximum 4 byte number in 4 bytes", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt4)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0xbf /* 10111111 */, 0xff, 0xff, 0xff}))
|
||
|
})
|
||
|
|
||
|
It("writes the minimum 8 byte number in 8 bytes", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt4+1)
|
||
|
Expect(b.Len()).To(Equal(8))
|
||
|
num, err := ReadVarInt(b)
|
||
|
Expect(err).ToNot(HaveOccurred())
|
||
|
Expect(num).To(Equal(uint64(maxVarInt4 + 1)))
|
||
|
})
|
||
|
|
||
|
It("writes an 8 byte number", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, 151288809941952652)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c}))
|
||
|
})
|
||
|
|
||
|
It("writes the maximum 8 byte number in 8 bytes", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
WriteVarInt(b, maxVarInt8)
|
||
|
Expect(b.Bytes()).To(Equal([]byte{0xff /* 11111111 */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}))
|
||
|
})
|
||
|
|
||
|
It("panics when given a too large number (> 62 bit)", func() {
|
||
|
b := &bytes.Buffer{}
|
||
|
Expect(func() { WriteVarInt(b, maxVarInt8+1) }).Should(Panic())
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("determining the length needed for encoding", func() {
|
||
|
It("for numbers that need 1 byte", func() {
|
||
|
Expect(VarIntLen(0)).To(BeEquivalentTo(1))
|
||
|
Expect(VarIntLen(maxVarInt1)).To(BeEquivalentTo(1))
|
||
|
})
|
||
|
|
||
|
It("for numbers that need 2 bytes", func() {
|
||
|
Expect(VarIntLen(maxVarInt1 + 1)).To(BeEquivalentTo(2))
|
||
|
Expect(VarIntLen(maxVarInt2)).To(BeEquivalentTo(2))
|
||
|
})
|
||
|
|
||
|
It("for numbers that need 4 bytes", func() {
|
||
|
Expect(VarIntLen(maxVarInt2 + 1)).To(BeEquivalentTo(4))
|
||
|
Expect(VarIntLen(maxVarInt4)).To(BeEquivalentTo(4))
|
||
|
})
|
||
|
|
||
|
It("for numbers that need 8 bytes", func() {
|
||
|
Expect(VarIntLen(maxVarInt4 + 1)).To(BeEquivalentTo(8))
|
||
|
Expect(VarIntLen(maxVarInt8)).To(BeEquivalentTo(8))
|
||
|
})
|
||
|
|
||
|
It("panics when given a too large number (> 62 bit)", func() {
|
||
|
Expect(func() { VarIntLen(maxVarInt8 + 1) }).Should(Panic())
|
||
|
})
|
||
|
})
|
||
|
})
|