From 039ca1d91ba976a23b3b2d456431ef66774eb765 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Sat, 9 Jan 2016 12:27:20 -0700 Subject: [PATCH] fix roaring array append This commit fixes a bug where appends to an array container did not cause it to roll over to a bitmap container when it reached the max array size. --- roaring/roaring.go | 2 +- roaring/roaring_test.go | 31 +++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index a86ed6863..6aa49579c 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -439,7 +439,7 @@ func (c *container) add(v uint16) { func (c *container) arrayAdd(v uint16) { // Optimize appending to the end of an array container. - if c.n > 0 && c.isArray() && c.array[c.n-1] < v { + if c.n > 0 && c.n < arrayMaxSize && c.isArray() && c.array[c.n-1] < v { c.unmap() c.array = append(c.array, v) c.n++ diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index 8e008845d..c25268878 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -117,21 +117,27 @@ func testBitmapQuick(t *testing.T, n int, min, max uint64) { return true }, &quick.Config{ Values: func(values []reflect.Value, rand *rand.Rand) { - values[0] = reflect.ValueOf(GenerateUint64Slice(n, min, max, rand)) + values[0] = reflect.ValueOf(GenerateUint64Slice(n, min, max, false, rand)) }, }) } -func TestBitmap_Marshal_Quick_Array1(t *testing.T) { testBitmapMarshalQuick(t, 1000, 1000, 2000) } -func TestBitmap_Marshal_Quick_Array2(t *testing.T) { testBitmapMarshalQuick(t, 10000, 0, 1000) } -func TestBitmap_Marshal_Quick_Bitmap1(t *testing.T) { testBitmapMarshalQuick(t, 10000, 0, 10000) } -func TestBitmap_Marshal_Quick_Bitmap2(t *testing.T) { testBitmapMarshalQuick(t, 10000, 10000, 20000) } +func TestBitmap_Marshal_Quick_Array1(t *testing.T) { testBitmapMarshalQuick(t, 1000, 1000, 2000, false) } +func TestBitmap_Marshal_Quick_Array2(t *testing.T) { testBitmapMarshalQuick(t, 10000, 0, 1000, false) } +func TestBitmap_Marshal_Quick_Bitmap1(t *testing.T) { testBitmapMarshalQuick(t, 10000, 0, 10000, false) } +func TestBitmap_Marshal_Quick_Bitmap2(t *testing.T) { + testBitmapMarshalQuick(t, 10000, 10000, 20000, false) +} func TestBitmap_Marshal_Quick_LargeValue(t *testing.T) { - testBitmapMarshalQuick(t, 100, 0, math.MaxInt64) + testBitmapMarshalQuick(t, 100, 0, math.MaxInt64, false) +} + +func TestBitmap_Marshal_Quick_Bitmap_Sorted(t *testing.T) { + testBitmapMarshalQuick(t, 10000, 0, 10000, true) } // Ensure a bitmap can be marshaled and unmarshaled. -func testBitmapMarshalQuick(t *testing.T, n int, min, max uint64) { +func testBitmapMarshalQuick(t *testing.T, n int, min, max uint64, sorted bool) { if testing.Short() { t.Skip("short") } @@ -186,18 +192,23 @@ func testBitmapMarshalQuick(t *testing.T, n int, min, max uint64) { return true }, &quick.Config{ Values: func(values []reflect.Value, rand *rand.Rand) { - values[0] = reflect.ValueOf(GenerateUint64Slice(n, min, max, rand)) - values[1] = reflect.ValueOf(GenerateUint64Slice(100, min, max, rand)) + values[0] = reflect.ValueOf(GenerateUint64Slice(n, min, max, sorted, rand)) + values[1] = reflect.ValueOf(GenerateUint64Slice(100, min, max, sorted, rand)) }, }) } // GenerateUint64Slice generates between [0, n) random uint64 numbers between min and max. -func GenerateUint64Slice(n int, min, max uint64, rand *rand.Rand) []uint64 { +func GenerateUint64Slice(n int, min, max uint64, sorted bool, rand *rand.Rand) []uint64 { a := make([]uint64, rand.Intn(n)) for i := range a { a[i] = min + uint64(rand.Int63n(int64(max-min))) } + + if sorted { + sort.Sort(uint64Slice(a)) + } + return a }