加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
serialization_test.go 14.46 KB
一键复制 编辑 原始数据 按行查看 历史
alex.sharov 提交于 2020-11-21 18:07 . remove msgpack support
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
package roaring
// to run just these tests: go test -run TestSerialization*
import (
"bytes"
"encoding/binary"
"encoding/gob"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSerializationOfEmptyBitmap(t *testing.T) {
rb := NewBitmap()
buf := &bytes.Buffer{}
_, err := rb.WriteTo(buf)
assert.NoError(t, err)
assert.EqualValues(t, buf.Len(), rb.GetSerializedSizeInBytes())
newrb := NewBitmap()
_, err = newrb.ReadFrom(buf)
assert.NoError(t, err)
assert.True(t, rb.Equals(newrb))
}
func TestBase64_036(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000)
bstr, _ := rb.ToBase64()
assert.NotEmpty(t, bstr)
newrb := NewBitmap()
_, err := newrb.FromBase64(bstr)
assert.NoError(t, err)
assert.True(t, rb.Equals(newrb))
}
func TestSerializationBasic037(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000)
buf := &bytes.Buffer{}
_, err := rb.WriteTo(buf)
assert.NoError(t, err)
assert.EqualValues(t, buf.Len(), rb.GetSerializedSizeInBytes())
newrb := NewBitmap()
_, err = newrb.ReadFrom(buf)
assert.NoError(t, err)
assert.True(t, rb.Equals(newrb))
}
func TestSerializationToFile038(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000)
fname := "myfile.bin"
fout, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0660)
assert.NoError(t, err)
var l int64
l, err = rb.WriteTo(fout)
assert.NoError(t, err)
assert.EqualValues(t, l, rb.GetSerializedSizeInBytes())
fout.Close()
newrb := NewBitmap()
fin, err := os.Open(fname)
assert.NoError(t, err)
defer func() {
fin.Close()
assert.NoError(t, os.Remove(fname))
}()
_, _ = newrb.ReadFrom(fin)
assert.True(t, rb.Equals(newrb))
}
func TestSerializationReadRunsFromFile039(t *testing.T) {
fn := "testdata/bitmapwithruns.bin"
by, err := ioutil.ReadFile(fn)
assert.NoError(t, err)
newrb := NewBitmap()
_, err = newrb.ReadFrom(bytes.NewBuffer(by))
assert.NoError(t, err)
}
func TestSerializationBasic4WriteAndReadFile040(t *testing.T) {
fname := "testdata/all3.classic"
rb := NewBitmap()
for k := uint32(0); k < 100000; k += 1000 {
rb.Add(k)
}
for k := uint32(100000); k < 200000; k++ {
rb.Add(3 * k)
}
for k := uint32(700000); k < 800000; k++ {
rb.Add(k)
}
rb.highlowcontainer.runOptimize()
fout, err := os.Create(fname)
assert.NoError(t, err)
var l int64
l, err = rb.WriteTo(fout)
assert.NoError(t, err)
assert.EqualValues(t, l, rb.GetSerializedSizeInBytes())
fout.Close()
fin, err := os.Open(fname)
assert.NoError(t, err)
defer fin.Close()
newrb := NewBitmap()
_, err = newrb.ReadFrom(fin)
assert.NoError(t, err)
assert.True(t, rb.Equals(newrb))
}
func TestSerializationFromJava051(t *testing.T) {
fname := "testdata/bitmapwithoutruns.bin"
newrb := NewBitmap()
fin, err := os.Open(fname)
assert.NoError(t, err)
defer func() {
fin.Close()
}()
_, _ = newrb.ReadFrom(fin)
fmt.Println(newrb.GetCardinality())
rb := NewBitmap()
for k := uint32(0); k < 100000; k += 1000 {
rb.Add(k)
}
for k := uint32(100000); k < 200000; k++ {
rb.Add(3 * k)
}
for k := uint32(700000); k < 800000; k++ {
rb.Add(k)
}
assert.True(t, rb.Equals(newrb))
}
func TestSerializationFromJavaWithRuns052(t *testing.T) {
fname := "testdata/bitmapwithruns.bin"
newrb := NewBitmap()
fin, err := os.Open(fname)
assert.NoError(t, err)
defer func() {
fin.Close()
}()
_, _ = newrb.ReadFrom(fin)
rb := NewBitmap()
for k := uint32(0); k < 100000; k += 1000 {
rb.Add(k)
}
for k := uint32(100000); k < 200000; k++ {
rb.Add(3 * k)
}
for k := uint32(700000); k < 800000; k++ {
rb.Add(k)
}
assert.True(t, rb.Equals(newrb))
}
func TestSerializationBasic2_041(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000, 10000, 100000, 1000000)
buf := &bytes.Buffer{}
sz := rb.GetSerializedSizeInBytes()
ub := BoundSerializedSizeInBytes(rb.GetCardinality(), 1000001)
assert.False(t, sz > ub+10)
l := int(rb.GetSerializedSizeInBytes())
_, err := rb.WriteTo(buf)
assert.NoError(t, err)
assert.Equal(t, l, buf.Len())
newrb := NewBitmap()
_, err = newrb.ReadFrom(buf)
assert.NoError(t, err)
assert.True(t, rb.Equals(newrb))
}
// roaringarray.writeTo and .readFrom should serialize and unserialize when containing all 3 container types
func TestSerializationBasic3_042(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000, 10000, 100000, 1000000)
for i := 5000000; i < 5000000+2*(1<<16); i++ {
rb.AddInt(i)
}
// confirm all three types present
var bc, ac, rc bool
for _, v := range rb.highlowcontainer.containers {
switch cn := v.(type) {
case *bitmapContainer:
bc = true
case *arrayContainer:
ac = true
case *runContainer16:
rc = true
default:
panic(fmt.Errorf("Unrecognized container implementation: %T", cn))
}
}
assert.True(t, bc, "no bitmapContainer found, change your test input so we test all three!")
assert.True(t, ac, "no arrayContainer found, change your test input so we test all three!")
assert.True(t, rc, "no runContainer16 found, change your test input so we test all three!")
var buf bytes.Buffer
_, err := rb.WriteTo(&buf)
assert.NoError(t, err)
assert.EqualValues(t, buf.Len(), rb.GetSerializedSizeInBytes())
newrb := NewBitmap()
_, err = newrb.ReadFrom(&buf)
assert.NoError(t, err)
assert.Equal(t, rb.GetCardinality(), newrb.GetCardinality())
assert.True(t, newrb.Equals(rb))
}
func TestGobcoding043(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000)
buf := new(bytes.Buffer)
encoder := gob.NewEncoder(buf)
err := encoder.Encode(rb)
assert.NoError(t, err)
var b Bitmap
decoder := gob.NewDecoder(buf)
err = decoder.Decode(&b)
assert.NoError(t, err)
assert.True(t, b.Equals(rb))
}
func TestByteSliceAsUint16Slice(t *testing.T) {
t.Run("valid slice", func(t *testing.T) {
expectedSize := 2
slice := make([]byte, 4)
binary.LittleEndian.PutUint16(slice, 42)
binary.LittleEndian.PutUint16(slice[2:], 43)
uint16Slice := byteSliceAsUint16Slice(slice)
assert.Equal(t, expectedSize, len(uint16Slice))
assert.Equal(t, expectedSize, cap(uint16Slice))
assert.False(t, uint16Slice[0] != 42 || uint16Slice[1] != 43)
})
t.Run("inlined", func(t *testing.T) {
first, second := singleSliceInArray()
t.Logf("received %v %v", first, second[0])
if !first.Equals(second[0]) {
t.Errorf("inline fail %v %v", first, second[0])
}
})
t.Run("empty slice", func(t *testing.T) {
slice := make([]byte, 0, 0)
uint16Slice := byteSliceAsUint16Slice(slice)
assert.Equal(t, 0, len(uint16Slice))
assert.Equal(t, 0, cap(uint16Slice))
})
t.Run("invalid slice size", func(t *testing.T) {
slice := make([]byte, 1, 1)
assert.Panics(t, func() {
byteSliceAsUint16Slice(slice)
})
})
}
func singleSliceInArray() (*Bitmap, []*Bitmap) {
firstSlice := singleSlice()
containerSlice := make([]*Bitmap, 0)
secondContainer := singleSlice()
containerSlice = append(containerSlice, secondContainer)
return firstSlice, containerSlice
}
func singleSlice() *Bitmap {
slice := make([]byte, 2)
return &Bitmap{highlowcontainer: roaringArray{keys: []uint16{0}, containers: []container{&arrayContainer{byteSliceAsUint16Slice(slice)}}}}
}
func TestByteSliceAsUint64Slice(t *testing.T) {
t.Run("valid slice", func(t *testing.T) {
expectedSize := 2
slice := make([]byte, 16)
binary.LittleEndian.PutUint64(slice, 42)
binary.LittleEndian.PutUint64(slice[8:], 43)
uint64Slice := byteSliceAsUint64Slice(slice)
assert.Equal(t, expectedSize, len(uint64Slice))
assert.Equal(t, expectedSize, cap(uint64Slice))
assert.False(t, uint64Slice[0] != 42 || uint64Slice[1] != 43)
})
t.Run("empty slice", func(t *testing.T) {
slice := make([]byte, 0, 0)
uint64Slice := byteSliceAsUint64Slice(slice)
assert.Equal(t, 0, len(uint64Slice))
assert.Equal(t, 0, cap(uint64Slice))
})
t.Run("invalid slice size", func(t *testing.T) {
slice := make([]byte, 1, 1)
assert.Panics(t, func() {
byteSliceAsUint64Slice(slice)
})
})
}
func TestByteSliceAsInterval16Slice(t *testing.T) {
t.Run("valid slice", func(t *testing.T) {
expectedSize := 2
slice := make([]byte, 8)
binary.LittleEndian.PutUint16(slice, 10)
binary.LittleEndian.PutUint16(slice[2:], 2)
binary.LittleEndian.PutUint16(slice[4:], 20)
binary.LittleEndian.PutUint16(slice[6:], 2)
intervalSlice := byteSliceAsInterval16Slice(slice)
assert.Equal(t, expectedSize, len(intervalSlice))
assert.Equal(t, expectedSize, cap(intervalSlice))
i1 := newInterval16Range(10, 12)
i2 := newInterval16Range(20, 22)
assert.False(t, intervalSlice[0] != i1 || intervalSlice[1] != i2)
})
t.Run("empty slice", func(t *testing.T) {
slice := make([]byte, 0, 0)
intervalSlice := byteSliceAsInterval16Slice(slice)
assert.Equal(t, 0, len(intervalSlice))
assert.Equal(t, 0, cap(intervalSlice))
})
t.Run("invalid slice length", func(t *testing.T) {
slice := make([]byte, 1, 1)
assert.Panics(t, func() {
byteSliceAsInterval16Slice(slice)
})
})
}
func TestBitmap_FromBuffer(t *testing.T) {
t.Run("empty bitmap", func(t *testing.T) {
rb := NewBitmap()
buf := &bytes.Buffer{}
_, err := rb.WriteTo(buf)
assert.NoError(t, err)
assert.EqualValues(t, buf.Len(), rb.GetSerializedSizeInBytes())
newRb := NewBitmap()
newRb.FromBuffer(buf.Bytes())
assert.NoError(t, err)
assert.True(t, rb.Equals(newRb))
})
t.Run("basic bitmap of 7 elements", func(t *testing.T) {
rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000)
buf := &bytes.Buffer{}
_, err := rb.WriteTo(buf)
assert.NoError(t, err)
newRb := NewBitmap()
_, err = newRb.FromBuffer(buf.Bytes())
assert.NoError(t, err)
assert.True(t, rb.Equals(newRb))
})
t.Run("bitmap with runs", func(t *testing.T) {
file := "testdata/bitmapwithruns.bin"
buf, err := ioutil.ReadFile(file)
assert.NoError(t, err)
rb := NewBitmap()
_, err = rb.FromBuffer(buf)
assert.NoError(t, err)
assert.EqualValues(t, 3, rb.Stats().RunContainers)
assert.EqualValues(t, 11, rb.Stats().Containers)
})
t.Run("bitmap without runs", func(t *testing.T) {
fn := "testdata/bitmapwithruns.bin"
buf, err := ioutil.ReadFile(fn)
assert.NoError(t, err)
rb := NewBitmap()
_, err = rb.FromBuffer(buf)
assert.NoError(t, err)
})
// all3.classic somehow created by other tests.
t.Run("all3.classic bitmap", func(t *testing.T) {
file := "testdata/all3.classic"
buf, err := ioutil.ReadFile(file)
assert.NoError(t, err)
rb := NewBitmap()
_, err = rb.FromBuffer(buf)
assert.NoError(t, err)
})
t.Run("testdata/bitmapwithruns.bin bitmap Ops", func(t *testing.T) {
file := "testdata/bitmapwithruns.bin"
buf, err := ioutil.ReadFile(file)
assert.NoError(t, err)
empt := NewBitmap()
rb1 := NewBitmap()
_, err = rb1.FromBuffer(buf)
assert.NoError(t, err)
rb2 := NewBitmap()
_, err = rb2.FromBuffer(buf)
assert.NoError(t, err)
rbor := Or(rb1, rb2)
rbfastor := FastOr(rb1, rb2)
rband := And(rb1, rb2)
rbxor := Xor(rb1, rb2)
rbandnot := AndNot(rb1, rb2)
assert.True(t, rbor.Equals(rb1))
assert.True(t, rbfastor.Equals(rbor))
assert.True(t, rband.Equals(rb1))
assert.True(t, rbxor.Equals(empt))
assert.True(t, rbandnot.Equals(empt))
})
t.Run("marking all containers as requiring COW", func(t *testing.T) {
file := "testdata/bitmapwithruns.bin"
buf, err := ioutil.ReadFile(file)
assert.NoError(t, err)
rb := NewBitmap()
_, err = rb.FromBuffer(buf)
assert.NoError(t, err)
for i, cow := range rb.highlowcontainer.needCopyOnWrite {
assert.Truef(t, cow, "Container at pos %d was not marked as needs-copy-on-write", i)
}
})
}
func TestSerializationCrashers(t *testing.T) {
crashers, err := filepath.Glob("testdata/crash*")
assert.NoError(t, err)
for _, crasher := range crashers {
data, err := ioutil.ReadFile(crasher)
assert.NoError(t, err)
// take a copy in case the stream is modified during unpacking attempt
orig := make([]byte, len(data))
copy(orig, data)
_, err = NewBitmap().FromBuffer(data)
assert.Error(t, err)
// reset for next one
copy(data, orig)
_, err = NewBitmap().ReadFrom(bytes.NewReader(data))
assert.Error(t, err)
}
}
func TestBitmapFromBufferCOW(t *testing.T) {
rbbogus := NewBitmap()
rbbogus.Add(100)
rbbogus.Add(100000)
rb1 := NewBitmap()
rb1.Add(1)
buf1 := &bytes.Buffer{}
rb1.WriteTo(buf1)
rb2 := NewBitmap()
rb2.Add(1000000)
buf2 := &bytes.Buffer{}
rb2.WriteTo(buf2)
newRb1 := NewBitmap()
newRb1.FromBuffer(buf1.Bytes())
newRb2 := NewBitmap()
newRb2.FromBuffer(buf2.Bytes())
rbor1 := Or(newRb1, newRb2)
rbor2 := rbor1
rbor3 := Or(newRb1, newRb2)
rbor1.CloneCopyOnWriteContainers()
rbor2.CloneCopyOnWriteContainers()
rbor3.CloneCopyOnWriteContainers()
buf1.Reset()
buf2.Reset()
rbbogus.WriteTo(buf1)
rbbogus.WriteTo(buf2)
rbexpected := NewBitmap()
rbexpected.Add(1)
rbexpected.Add(1000000)
assert.True(t, rbexpected.Equals(rbor2))
assert.True(t, rbexpected.Equals(rbor3))
}
func TestHoldReference(t *testing.T) {
t.Run("Test Hold Reference", func(t *testing.T) {
rb := New()
buf := &bytes.Buffer{}
for i := uint32(0); i < 650; i++ {
rb.Add(i)
}
_, err := rb.WriteTo(buf)
assert.NoError(t, err)
nb := New()
data := buf.Bytes()
_, err = nb.ReadFrom(bytes.NewReader(data))
assert.NoError(t, err)
buf = nil
rb = nil
data = nil
runtime.GC()
iterator := nb.Iterator()
i := uint32(0)
for iterator.HasNext() {
v := iterator.Next()
if v != i {
return
}
assert.Equal(t, i, v)
i++
}
})
}
func BenchmarkUnserializeReadFrom(b *testing.B) {
for _, size := range []uint32{650, 6500, 65000, 650000, 6500000} {
rb := New()
buf := &bytes.Buffer{}
for i := uint32(0); i < size; i++ {
rb.Add(i)
}
_, err := rb.WriteTo(buf)
if err != nil {
b.Fatalf("Unexpected error occurs: %v", err)
}
b.Run(fmt.Sprintf("ReadFrom-%d", size), func(b *testing.B) {
b.ReportAllocs()
b.StartTimer()
for n := 0; n < b.N; n++ {
reader := bytes.NewReader(buf.Bytes())
nb := New()
if _, err := nb.ReadFrom(reader); err != nil {
b.Fatalf("Unexpected error occurs: %v", err)
}
}
b.StopTimer()
})
}
}
func BenchmarkUnserializeFromBuffer(b *testing.B) {
for _, size := range []uint32{650, 6500, 65000, 650000, 6500000} {
rb := New()
buf := &bytes.Buffer{}
for i := uint32(0); i < size; i++ {
rb.Add(i)
}
_, err := rb.WriteTo(buf)
if err != nil {
b.Fatalf("Unexpected error occurs: %v", err)
}
b.Run(fmt.Sprintf("FromBuffer-%d", size), func(b *testing.B) {
b.ReportAllocs()
b.StartTimer()
for n := 0; n < b.N; n++ {
nb := New()
if _, err := nb.FromBuffer(buf.Bytes()); err != nil {
b.Fatalf("Unexpected error occurs: %v", err)
}
}
b.StopTimer()
})
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化