3d6071ed3f
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package bitvector_test
|
|
|
|
import (
|
|
"runtime"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
bitvector "github.com/filecoin-project/go-lotus/lib/rlepluslazy/internal"
|
|
)
|
|
|
|
func TestBitVector(t *testing.T) {
|
|
t.Run("zero value", func(t *testing.T) {
|
|
var v bitvector.BitVector
|
|
|
|
assert.Equal(t, bitvector.LSB0, v.BytePacking)
|
|
})
|
|
|
|
t.Run("Push", func(t *testing.T) {
|
|
// MSB0 bit numbering
|
|
v := bitvector.BitVector{BytePacking: bitvector.MSB0}
|
|
v.Push(1)
|
|
v.Push(0)
|
|
v.Push(1)
|
|
v.Push(1)
|
|
|
|
assert.Equal(t, byte(176), v.Buf[0])
|
|
|
|
// LSB0 bit numbering
|
|
v = bitvector.BitVector{BytePacking: bitvector.LSB0}
|
|
v.Push(1)
|
|
v.Push(0)
|
|
v.Push(1)
|
|
v.Push(1)
|
|
|
|
assert.Equal(t, byte(13), v.Buf[0])
|
|
})
|
|
|
|
t.Run("Get", func(t *testing.T) {
|
|
bits := []byte{1, 0, 1, 1, 0, 0, 1, 0}
|
|
|
|
for _, numbering := range []bitvector.BitNumbering{bitvector.MSB0, bitvector.LSB0} {
|
|
v := bitvector.BitVector{BytePacking: numbering}
|
|
|
|
for _, bit := range bits {
|
|
v.Push(bit)
|
|
}
|
|
|
|
for idx, expected := range bits {
|
|
actual, _ := v.Get(uint(idx))
|
|
assert.Equal(t, expected, actual)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("Extend", func(t *testing.T) {
|
|
val := byte(171) // 0b10101011
|
|
|
|
var v bitvector.BitVector
|
|
|
|
// MSB0 bit numbering
|
|
v = bitvector.BitVector{}
|
|
v.Extend(val, 4, bitvector.MSB0)
|
|
assertBitVector(t, []byte{1, 0, 1, 0}, v)
|
|
v.Extend(val, 5, bitvector.MSB0)
|
|
assertBitVector(t, []byte{1, 0, 1, 0, 1, 0, 1, 0, 1}, v)
|
|
|
|
// LSB0 bit numbering
|
|
v = bitvector.BitVector{}
|
|
v.Extend(val, 4, bitvector.LSB0)
|
|
assertBitVector(t, []byte{1, 1, 0, 1}, v)
|
|
v.Extend(val, 5, bitvector.LSB0)
|
|
assertBitVector(t, []byte{1, 1, 0, 1, 1, 1, 0, 1, 0}, v)
|
|
})
|
|
|
|
t.Run("invalid counts to Take/Extend/Iterator cause panics", func(t *testing.T) {
|
|
v := bitvector.BitVector{BytePacking: bitvector.LSB0}
|
|
|
|
assert.Panics(t, func() { v.Extend(0xff, 9, bitvector.LSB0) })
|
|
|
|
assert.Panics(t, func() { v.Take(0, 9, bitvector.LSB0) })
|
|
|
|
next := v.Iterator(bitvector.LSB0)
|
|
assert.Panics(t, func() { next(9) })
|
|
})
|
|
|
|
t.Run("Take", func(t *testing.T) {
|
|
var v bitvector.BitVector
|
|
|
|
bits := []byte{1, 0, 1, 0, 1, 0, 1, 1}
|
|
for _, bit := range bits {
|
|
v.Push(bit)
|
|
}
|
|
|
|
assert.Equal(t, byte(176), v.Take(4, 4, bitvector.MSB0))
|
|
assert.Equal(t, byte(13), v.Take(4, 4, bitvector.LSB0))
|
|
})
|
|
|
|
t.Run("Iterator", func(t *testing.T) {
|
|
var buf []byte
|
|
|
|
// make a bitvector of 256 sample bits
|
|
for i := 0; i < 1000; i++ {
|
|
buf = append(buf, byte(i))
|
|
}
|
|
|
|
v := bitvector.NewBitVector(buf, bitvector.LSB0)
|
|
|
|
next := v.Iterator(bitvector.LSB0)
|
|
|
|
// compare to Get()
|
|
for i := uint(0); i < v.Len; i++ {
|
|
expected, _ := v.Get(i)
|
|
assert.Equal(t, expected, next(1), "at index %d", i)
|
|
}
|
|
|
|
// out of range should return zero
|
|
assert.Equal(t, byte(0), next(1))
|
|
assert.Equal(t, byte(0), next(8))
|
|
|
|
// compare to Take()
|
|
next = v.Iterator(bitvector.LSB0)
|
|
assert.Equal(t, next(5), v.Take(0, 5, bitvector.LSB0))
|
|
assert.Equal(t, next(8), v.Take(5, 8, bitvector.LSB0))
|
|
})
|
|
}
|
|
|
|
// Note: When using this helper assertion, expectedBits should *only* be 0s and 1s.
|
|
func assertBitVector(t *testing.T, expectedBits []byte, actual bitvector.BitVector) {
|
|
assert.Equal(t, uint(len(expectedBits)), actual.Len)
|
|
|
|
for idx, bit := range expectedBits {
|
|
actualBit, err := actual.Get(uint(idx))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, bit, actualBit)
|
|
}
|
|
}
|
|
|
|
func BenchmarkTake(b *testing.B) {
|
|
buf := make([]byte, 0, 128)
|
|
for i := 0; i < 128; i++ {
|
|
buf = append(buf, byte(128+i))
|
|
}
|
|
|
|
v := bitvector.NewBitVector(buf, bitvector.LSB0)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
next := v.Iterator(bitvector.LSB0)
|
|
for i := 0; i < b.N; i++ {
|
|
runtime.KeepAlive(next(8))
|
|
}
|
|
}
|