featurebase/roaring/containers_test.go
Seebs 47dcb5b4a7 Abstract away access to container slices
On a 64-bit machine, the slices in a Container consume 72
bytes, and the Container itself is 80. But we only use one
slice at a time! This patch shifts us to keeping a single
slice in the Container, and converting provided slices to
and from that type when we want to update it. (It is not
safe to access the slice through the wrong type.)

We also add some new tests, conditional on a build tag
called `roaringparanoia`. These tests will be optimized
away entirely by the compiler when the tag isn't
present, because the conditionals use a const. These catch
possible errors like trying to access the bitmap slice
of a non-bitmap container.

We also eliminate all direct creation of Container literals,
so we can mess with the internals more. (On reflection
and study, we decided not to go to the fancier design where
references to .n and .typ were also converted to function
calls, which would have allowed packing those attributes
more tightly, because it was a lot more overhead and a lot
of work to keep track of.)

There's some circumstances where we appear to have been
relying on incorrect guesses about the nature of containers.
For instance, in xorBitmapRun, there's logic that makes sense
only if the output's a run container, but it's not, it's a
bitmap container. This creates strange behavior sometimes,
though. Several of these are corrected now.
2019-03-22 16:31:29 -05:00

102 lines
2.7 KiB
Go

// Copyright (C) 2017-2018 Pilosa Corp. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package roaring
import (
"testing"
)
func TestContainersIterator(t *testing.T) {
slc := NewFileBitmap().Containers
testContainersIterator(slc, t)
}
func testContainersIterator(cs Containers, t *testing.T) {
itr, found := cs.Iterator(0)
if found {
t.Fatalf("shouldn't have found 0 in empty btc")
}
if itr.Next() {
t.Fatal("Next() should be false for empty btc")
}
cs.Put(1, NewContainerArray([]uint16{1}))
cs.Put(2, NewContainerArray([]uint16{1, 2}))
itr, found = cs.Iterator(0)
if found {
t.Fatalf("shouldn't have found 0")
}
if !itr.Next() {
t.Fatalf("one should be next, but got false")
}
if key, val := itr.Value(); key != 1 || val.n != 1 {
t.Fatalf("Wrong k/v, exp: 1,1 got: %v,%v", key, val.n)
}
if !itr.Next() {
t.Fatalf("two should be next, but got false")
}
if key, val := itr.Value(); key != 2 || val.n != 2 {
t.Fatalf("Wrong k/v, exp: 2,2 got: %v,%v", key, val.n)
}
if itr.Next() {
t.Fatalf("itr should be done, but got true")
}
cs.Put(3, NewContainerArray([]uint16{1, 2, 3}))
cs.Put(5, NewContainerArray([]uint16{1, 2, 3, 4, 5}))
cs.Put(6, NewContainerArray([]uint16{1, 2, 3, 4, 5, 6}))
itr, found = cs.Iterator(3)
if !itr.Next() {
t.Fatalf("3 should be next, but got false")
}
if !found {
t.Fatalf("should have found 3")
}
if key, val := itr.Value(); key != 3 || val.n != 3 {
t.Fatalf("Wrong k/v, exp: 3,3 got: %v,%v", key, val.n)
}
if !itr.Next() {
t.Fatalf("5 should be next, but got false")
}
if key, val := itr.Value(); key != 5 || val.n != 5 {
t.Fatalf("Wrong k/v, exp: 5,5 got: %v,%v", key, val.n)
}
itr, found = cs.Iterator(4)
if found {
t.Fatalf("shouldn't have found 4")
}
if !itr.Next() {
t.Fatalf("5 should be next, but got false")
}
if key, val := itr.Value(); key != 5 || val.n != 5 {
t.Fatalf("Wrong k/v, exp: 5,5 got: %v,%v", key, val.n)
}
if !itr.Next() {
t.Fatalf("6 should be next, but got false")
}
if key, val := itr.Value(); key != 6 || val.n != 6 {
t.Fatalf("Wrong k/v, exp: 6,6 got: %v,%v", key, val.n)
}
if itr.Next() {
t.Fatalf("itr should be done, but got true")
}
}