mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-15 16:51:03 +00:00
1937 lines
50 KiB
Go
1937 lines
50 KiB
Go
// Copyright 2017 Pilosa Corp.
|
|
//
|
|
// 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 (
|
|
"bytes"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
// String produces a human viewable string of the contents.
|
|
func (iv interval32) String() string {
|
|
return fmt.Sprintf("[%d, %d]", iv.start, iv.last)
|
|
}
|
|
|
|
func (c *container) String() string {
|
|
return fmt.Sprintf("<%s container (%v), n=%d, array[%d], runs[%d], bitmap[%d]>", c.info().Type, &c, c.n, len(c.array), len(c.runs), len(c.bitmap))
|
|
}
|
|
|
|
func TestRunAppendInterval(t *testing.T) {
|
|
a := container{}
|
|
tests := []struct {
|
|
base []interval32
|
|
app interval32
|
|
exp int
|
|
}{
|
|
{
|
|
base: []interval32{},
|
|
app: interval32{start: 22, last: 25},
|
|
exp: 4,
|
|
},
|
|
{
|
|
base: []interval32{{start: 20, last: 23}},
|
|
app: interval32{start: 22, last: 25},
|
|
exp: 2,
|
|
},
|
|
{
|
|
base: []interval32{{start: 20, last: 23}},
|
|
app: interval32{start: 21, last: 22},
|
|
exp: 0,
|
|
},
|
|
{
|
|
base: []interval32{{start: 20, last: 23}},
|
|
app: interval32{start: 19, last: 25},
|
|
exp: 2, // runAppendInterval explicitly does not support intervals whose start is < c.runs[-1].start
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
a.runs = test.base
|
|
if n := a.runAppendInterval(test.app); n != test.exp {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, n)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestInterval32RunLen(t *testing.T) {
|
|
iv := interval32{start: 7, last: 9}
|
|
if iv.runlen() != 3 {
|
|
t.Fatalf("should be 3")
|
|
}
|
|
iv = interval32{start: 7, last: 7}
|
|
if iv.runlen() != 1 {
|
|
t.Fatalf("should be 1")
|
|
}
|
|
}
|
|
|
|
func TestContainerRunAdd(t *testing.T) {
|
|
c := container{runs: make([]interval32, 0)}
|
|
tests := []struct {
|
|
op uint32
|
|
exp []interval32
|
|
}{
|
|
{1, []interval32{{start: 1, last: 1}}},
|
|
{2, []interval32{{start: 1, last: 2}}},
|
|
{4, []interval32{{start: 1, last: 2}, {start: 4, last: 4}}},
|
|
{3, []interval32{{start: 1, last: 4}}},
|
|
{10, []interval32{{start: 1, last: 4}, {start: 10, last: 10}}},
|
|
{7, []interval32{{start: 1, last: 4}, {start: 7, last: 7}, {start: 10, last: 10}}},
|
|
{6, []interval32{{start: 1, last: 4}, {start: 6, last: 7}, {start: 10, last: 10}}},
|
|
{0, []interval32{{start: 0, last: 4}, {start: 6, last: 7}, {start: 10, last: 10}}},
|
|
{8, []interval32{{start: 0, last: 4}, {start: 6, last: 8}, {start: 10, last: 10}}},
|
|
}
|
|
for _, test := range tests {
|
|
c.mapped = true
|
|
ret := c.add(test.op)
|
|
if !ret {
|
|
t.Fatalf("result of adding new bit should be true: %v", c.runs)
|
|
}
|
|
if !reflect.DeepEqual(c.runs, test.exp) {
|
|
t.Fatalf("Should have %v, but got %v after adding %v", test.exp, c.runs, test.op)
|
|
}
|
|
if c.mapped {
|
|
t.Fatalf("container should not be mapped after adding bit %v", test.op)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestContainerRunAdd2(t *testing.T) {
|
|
c := container{runs: make([]interval32, 0)}
|
|
ret := c.add(0)
|
|
if !ret {
|
|
t.Fatalf("result of adding new bit should be true: %v", c.runs)
|
|
}
|
|
if !reflect.DeepEqual(c.runs, []interval32{{start: 0, last: 0}}) {
|
|
t.Fatalf("should have 1 run of length 1, but have %v", c.runs)
|
|
}
|
|
ret = c.add(0)
|
|
if ret {
|
|
t.Fatalf("result of adding existing bit should be false: %v", c.runs)
|
|
}
|
|
}
|
|
|
|
func TestRunCountRange(t *testing.T) {
|
|
c := container{runs: make([]interval32, 0)}
|
|
cnt := c.runCountRange(2, 9)
|
|
if cnt != 0 {
|
|
t.Fatalf("should get 0 from empty container, but got: %v", cnt)
|
|
}
|
|
c.add(5)
|
|
c.add(6)
|
|
c.add(7)
|
|
|
|
cnt = c.runCountRange(2, 9)
|
|
if cnt != 3 {
|
|
t.Fatalf("should get 3 from interval within range, but got: %v", cnt)
|
|
}
|
|
|
|
c.add(8)
|
|
c.add(9)
|
|
c.add(10)
|
|
c.add(11)
|
|
|
|
cnt = c.runCountRange(6, 8)
|
|
if cnt != 2 {
|
|
t.Fatalf("should get 2 from range within interval, but got: %v", cnt)
|
|
}
|
|
|
|
cnt = c.runCountRange(3, 9)
|
|
if cnt != 4 {
|
|
t.Fatalf("should get 4 from range overlaps front of interval, but got: %v", cnt)
|
|
}
|
|
|
|
cnt = c.runCountRange(9, 14)
|
|
if cnt != 3 {
|
|
t.Fatalf("should get 3 from range overlaps back of interval, but got: %v", cnt)
|
|
}
|
|
|
|
c.add(17)
|
|
c.add(18)
|
|
c.add(19)
|
|
|
|
cnt = c.runCountRange(1, 22)
|
|
if cnt != 10 {
|
|
t.Fatalf("should get 10 from multiple ranges in interval, but got: %v", cnt)
|
|
}
|
|
|
|
c.add(13)
|
|
c.add(14)
|
|
|
|
cnt = c.runCountRange(6, 18)
|
|
if cnt != 9 {
|
|
t.Fatalf("should get 9 from multiple ranges overlapping both sides, but got: %v", cnt)
|
|
}
|
|
}
|
|
|
|
func TestRunContains(t *testing.T) {
|
|
c := container{runs: make([]interval32, 0)}
|
|
if c.runContains(5) {
|
|
t.Fatalf("empty run container should not contain 5")
|
|
}
|
|
c.add(5)
|
|
if !c.runContains(5) {
|
|
t.Fatalf("run container with 5 should contain 5")
|
|
}
|
|
|
|
c.add(6)
|
|
c.add(7)
|
|
|
|
c.add(9)
|
|
c.add(10)
|
|
c.add(11)
|
|
|
|
if !c.runContains(10) {
|
|
t.Fatalf("run container with 10 in second run should contain 10")
|
|
}
|
|
}
|
|
|
|
func TestBitmapCountRange(t *testing.T) {
|
|
c := container{}
|
|
tests := []struct {
|
|
start uint32
|
|
end uint32
|
|
bitmap []uint64
|
|
exp int
|
|
}{
|
|
{start: 0, end: 1, bitmap: []uint64{1}, exp: 1},
|
|
{start: 2, end: 7, bitmap: []uint64{0xFFFFFFFFFFFFFF18}, exp: 2},
|
|
{start: 67, end: 68, bitmap: []uint64{0, 0x8}, exp: 1},
|
|
{start: 1, end: 68, bitmap: []uint64{0x3, 0x8, 0xF}, exp: 2},
|
|
{start: 1, end: 258, bitmap: []uint64{0xF, 0x8, 0xA, 0x4, 0xFFFFFFFFFFFFFFFF}, exp: 9},
|
|
{start: 66, end: 71, bitmap: []uint64{0xF, 0xFFFFFFFFFFFFFF18}, exp: 2},
|
|
{start: 63, end: 64, bitmap: []uint64{0x8000000000000000}, exp: 1},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
c.bitmap = test.bitmap
|
|
if ret := c.bitmapCountRange(test.start, test.end); ret != test.exp {
|
|
t.Fatalf("test #%v count of %v from %v to %v should be %v but got %v", i, test.bitmap, test.start, test.end, test.exp, ret)
|
|
}
|
|
}
|
|
|
|
c = container{bitmap: []uint64{0xF0000001, 0xFF000000, 0xFF00000000000000}}
|
|
cnt := c.bitmapCountRange(62, 129)
|
|
if cnt != 10 {
|
|
t.Fatalf("count of %v from 62 to 129 should be 10, but got %v", c.bitmap, cnt)
|
|
}
|
|
}
|
|
|
|
func TestIntersectionCountArrayBitmap2(t *testing.T) {
|
|
a, b := &container{}, &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
bitmap []uint64
|
|
exp uint64
|
|
}{
|
|
{
|
|
array: []uint32{0},
|
|
bitmap: []uint64{1},
|
|
exp: 1,
|
|
},
|
|
{
|
|
array: []uint32{0, 1},
|
|
bitmap: []uint64{3},
|
|
exp: 2,
|
|
},
|
|
{
|
|
array: []uint32{64, 128, 129, 2000},
|
|
bitmap: []uint64{932421, 2},
|
|
exp: 0,
|
|
},
|
|
{
|
|
array: []uint32{0, 65, 130, 195},
|
|
bitmap: []uint64{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
|
exp: 4,
|
|
},
|
|
{
|
|
array: []uint32{63, 120, 543, 639, 12000},
|
|
bitmap: []uint64{0x8000000000000000, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000000000000000},
|
|
exp: 2,
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
a.array = test.array
|
|
b.bitmap = test.bitmap
|
|
ret1 := intersectionCountArrayBitmapOld(a, b)
|
|
ret2 := intersectionCountArrayBitmap(a, b)
|
|
if ret1 != ret2 || ret2 != test.exp {
|
|
t.Fatalf("test #%v intersectCountArrayBitmap fail orig: %v new: %v exp: %v", i, ret1, ret2, test.exp)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRunRemove(t *testing.T) {
|
|
c := container{runs: []interval32{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}}
|
|
tests := []struct {
|
|
op uint32
|
|
exp []interval32
|
|
expRet bool
|
|
}{
|
|
{2, []interval32{{start: 3, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}, true},
|
|
{10, []interval32{{start: 3, last: 9}, {start: 12, last: 13}, {start: 15, last: 16}}, true},
|
|
{12, []interval32{{start: 3, last: 9}, {start: 13, last: 13}, {start: 15, last: 16}}, true},
|
|
{13, []interval32{{start: 3, last: 9}, {start: 15, last: 16}}, true},
|
|
{16, []interval32{{start: 3, last: 9}, {start: 15, last: 15}}, true},
|
|
{6, []interval32{{start: 3, last: 5}, {start: 7, last: 9}, {start: 15, last: 15}}, true},
|
|
{8, []interval32{{start: 3, last: 5}, {start: 7, last: 7}, {start: 9, last: 9}, {start: 15, last: 15}}, true},
|
|
{8, []interval32{{start: 3, last: 5}, {start: 7, last: 7}, {start: 9, last: 9}, {start: 15, last: 15}}, false},
|
|
{1, []interval32{{start: 3, last: 5}, {start: 7, last: 7}, {start: 9, last: 9}, {start: 15, last: 15}}, false},
|
|
{44, []interval32{{start: 3, last: 5}, {start: 7, last: 7}, {start: 9, last: 9}, {start: 15, last: 15}}, false},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
c.mapped = true
|
|
ret := c.remove(test.op)
|
|
if ret != test.expRet || !reflect.DeepEqual(c.runs, test.exp) {
|
|
t.Fatalf("test #%v Unexpected result removing %v from runs. Expected %v, got %v. Expected %v, got %v", i, test.op, test.expRet, ret, test.exp, c.runs)
|
|
}
|
|
if ret && c.mapped {
|
|
t.Fatalf("test #%v container was not unmapped although bit %v was removed", i, test.op)
|
|
}
|
|
if !ret && !c.mapped {
|
|
t.Fatalf("test #%v container was unmapped although bit %v was not removed", i, test.op)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRunMax(t *testing.T) {
|
|
c := container{runs: []interval32{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}}
|
|
max := c.max()
|
|
if max != 16 {
|
|
t.Fatalf("max for %v should be 16", c.runs)
|
|
}
|
|
|
|
c = container{runs: []interval32{}}
|
|
max = c.max()
|
|
if max != 0 {
|
|
t.Fatalf("max for %v should be 0", c.runs)
|
|
}
|
|
}
|
|
|
|
func TestIntersectionCountArrayRun(t *testing.T) {
|
|
a := &container{array: []uint32{1, 5, 10, 11, 12}}
|
|
b := &container{runs: []interval32{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}}
|
|
|
|
ret := intersectionCountArrayRun(a, b)
|
|
if ret != 3 {
|
|
t.Fatalf("count of %v with %v should be 3, but got %v", a.array, b.runs, ret)
|
|
}
|
|
}
|
|
|
|
func TestIntersectionCountBitmapRun(t *testing.T) {
|
|
a := &container{bitmap: []uint64{0x8000000000000000}}
|
|
b := &container{runs: []interval32{{start: 63, last: 64}}}
|
|
|
|
ret := intersectionCountBitmapRun(a, b)
|
|
if ret != 1 {
|
|
t.Fatalf("count of %v with %v should be 1, but got %v", a.bitmap, b.runs, ret)
|
|
}
|
|
|
|
a = &container{bitmap: []uint64{0xF0000001, 0xFF00000000000000, 0xFF000000000000F0, 0x0F0000}}
|
|
b = &container{runs: []interval32{{start: 29, last: 31}, {start: 125, last: 134}, {start: 191, last: 197}, {start: 200, last: 300}}}
|
|
|
|
ret = intersectionCountBitmapRun(a, b)
|
|
if ret != 14 {
|
|
t.Fatalf("count of %v with %v should be 14, but got %v", a.bitmap, b.runs, ret)
|
|
}
|
|
}
|
|
|
|
func TestIntersectionCountRunRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
aruns []interval32
|
|
bruns []interval32
|
|
exp uint64
|
|
}{
|
|
{
|
|
aruns: []interval32{},
|
|
bruns: []interval32{{start: 3, last: 8}}, exp: 0},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}},
|
|
bruns: []interval32{{start: 3, last: 8}}, exp: 6},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}},
|
|
bruns: []interval32{{start: 1, last: 11}}, exp: 9},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}},
|
|
bruns: []interval32{{start: 0, last: 2}}, exp: 1},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}},
|
|
bruns: []interval32{{start: 1, last: 10}}, exp: 9},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}},
|
|
bruns: []interval32{{start: 5, last: 12}}, exp: 6},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}},
|
|
bruns: []interval32{{start: 10, last: 99}}, exp: 1},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}, {start: 44, last: 99}},
|
|
bruns: []interval32{{start: 12, last: 14}}, exp: 0},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 10}, {start: 12, last: 13}},
|
|
bruns: []interval32{{start: 2, last: 10}, {start: 12, last: 13}}, exp: 11},
|
|
{
|
|
aruns: []interval32{{start: 8, last: 12}, {start: 15, last: 19}},
|
|
bruns: []interval32{{start: 9, last: 9}, {start: 11, last: 17}}, exp: 6},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.aruns
|
|
b.runs = test.bruns
|
|
ret := intersectionCountRunRun(a, b)
|
|
if ret != test.exp {
|
|
t.Fatalf("test #%v failed intersecting %v with %v should be %v, but got %v", i, test.aruns, test.bruns, test.exp, ret)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIntersectArrayRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
runs []interval32
|
|
exp []uint32
|
|
}{
|
|
{
|
|
array: []uint32{1, 4, 5, 7, 10, 11, 12},
|
|
runs: []interval32{{start: 5, last: 10}},
|
|
exp: []uint32{5, 7, 10},
|
|
},
|
|
{
|
|
array: []uint32{},
|
|
runs: []interval32{{start: 5, last: 10}},
|
|
exp: []uint32(nil),
|
|
},
|
|
{
|
|
array: []uint32{1, 4, 5, 7, 10, 11, 12},
|
|
runs: []interval32{},
|
|
exp: []uint32(nil),
|
|
},
|
|
{
|
|
array: []uint32{0, 1, 4, 5, 7, 10, 11, 12},
|
|
runs: []interval32{{start: 0, last: 5}, {start: 7, last: 7}},
|
|
exp: []uint32{0, 1, 4, 5, 7},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
a.array = test.array
|
|
b.runs = test.runs
|
|
ret := intersectArrayRun(a, b)
|
|
if !reflect.DeepEqual(ret.array, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIntersectRunRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
aruns []interval32
|
|
bruns []interval32
|
|
exp []interval32
|
|
expN int
|
|
}{
|
|
{
|
|
aruns: []interval32{},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32(nil),
|
|
expN: 0,
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 5, last: 12}},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 5, last: 10}},
|
|
expN: 6,
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 5, last: 5}, {start: 7, last: 10}},
|
|
expN: 5,
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 20, last: 30}},
|
|
bruns: []interval32{{start: 5, last: 10}, {start: 19, last: 21}},
|
|
exp: []interval32{{start: 20, last: 21}},
|
|
expN: 2,
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 5, last: 10}},
|
|
bruns: []interval32{{start: 7, last: 12}},
|
|
exp: []interval32{{start: 7, last: 10}},
|
|
expN: 4,
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 5, last: 12}},
|
|
bruns: []interval32{{start: 7, last: 10}},
|
|
exp: []interval32{{start: 7, last: 10}},
|
|
expN: 4,
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.aruns
|
|
b.runs = test.bruns
|
|
ret := intersectRunRun(a, b)
|
|
if ret.n != test.expN {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, ret.n)
|
|
}
|
|
if !reflect.DeepEqual(ret.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestIntersectBitmapRunBitmap(t *testing.T) {
|
|
a := &container{bitmap: make([]uint64, bitmapN)}
|
|
b := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
runs []interval32
|
|
exp []uint64
|
|
expN int
|
|
}{
|
|
{
|
|
bitmap: []uint64{1},
|
|
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 4096}},
|
|
exp: []uint64{1},
|
|
expN: 1,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 1, last: 1}},
|
|
exp: []uint64{2},
|
|
expN: 1,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 1, last: 1}, {start: 10, last: 12}, {start: 61, last: 77}},
|
|
exp: []uint64{0xe000000000001C02},
|
|
expN: 7,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 1, last: 1}, {start: 61, last: 77}},
|
|
exp: []uint64{0xE000000000000002, 0x00000000000003FFF},
|
|
expN: 18,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 1, 1, 1, 0xA, 1, 1, 0, 1},
|
|
runs: []interval32{{start: 63, last: 10000}},
|
|
exp: []uint64{0x8000000000000000, 1, 1, 1, 0xA, 1, 1, 0, 1},
|
|
expN: 9,
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
a.bitmap[i] = v
|
|
}
|
|
b.runs = test.runs
|
|
b.n = 4097 // ;)
|
|
exp := make([]uint64, bitmapN)
|
|
for i, v := range test.exp {
|
|
exp[i] = v
|
|
}
|
|
ret := intersectBitmapRun(a, b)
|
|
if ret.isArray() {
|
|
ret.arrayToBitmap()
|
|
}
|
|
if !reflect.DeepEqual(ret.bitmap, exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, exp, ret.bitmap)
|
|
}
|
|
if ret.n != test.expN {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, ret.n)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestIntersectBitmapRunArray(t *testing.T) {
|
|
a := &container{bitmap: make([]uint64, bitmapN)}
|
|
b := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
runs []interval32
|
|
exp []uint32
|
|
expN int
|
|
}{
|
|
{
|
|
bitmap: []uint64{1},
|
|
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 4096}},
|
|
exp: []uint32{0},
|
|
expN: 1,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 1, last: 1}},
|
|
exp: []uint32{1},
|
|
expN: 1,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 1, last: 1}, {start: 10, last: 12}, {start: 61, last: 77}},
|
|
exp: []uint32{1, 10, 11, 12, 61, 62, 63},
|
|
expN: 7,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 1, last: 1}, {start: 61, last: 68}},
|
|
exp: []uint32{1, 61, 62, 63, 64, 65, 66, 67, 68},
|
|
expN: 9,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 1, 1, 1, 0xA, 1, 1, 0, 1},
|
|
runs: []interval32{{start: 63, last: 10000}},
|
|
exp: []uint32{63, 64, 128, 192, 257, 259, 320, 384, 512},
|
|
expN: 9,
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
a.bitmap[i] = v
|
|
}
|
|
b.runs = test.runs
|
|
ret := intersectBitmapRun(a, b)
|
|
if !reflect.DeepEqual(ret.array, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
|
|
}
|
|
if ret.n != test.expN {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, ret.n)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestUnionRunRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
aruns []interval32
|
|
bruns []interval32
|
|
exp []interval32
|
|
}{
|
|
{
|
|
aruns: []interval32{},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 5, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 5, last: 12}},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 5, last: 12}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 1, last: 3}, {start: 5, last: 12}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}},
|
|
bruns: []interval32{{start: 2, last: 65535}},
|
|
exp: []interval32{{start: 1, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 65535}},
|
|
bruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}},
|
|
exp: []interval32{{start: 1, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}},
|
|
bruns: []interval32{{start: 0, last: 65535}},
|
|
exp: []interval32{{start: 0, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 65535}},
|
|
bruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 8}, {start: 9, last: 12}},
|
|
exp: []interval32{{start: 0, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 9}, {start: 12, last: 22}},
|
|
bruns: []interval32{{start: 2, last: 8}, {start: 16, last: 27}, {start: 33, last: 34}},
|
|
exp: []interval32{{start: 1, last: 9}, {start: 12, last: 27}, {start: 33, last: 34}},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.aruns
|
|
b.runs = test.bruns
|
|
ret := unionRunRun(a, b)
|
|
if !reflect.DeepEqual(ret.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnionArrayRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
runs []interval32
|
|
exp []uint32
|
|
}{
|
|
{
|
|
array: []uint32{1, 4, 5, 7, 10, 11, 12},
|
|
runs: []interval32{{start: 5, last: 10}},
|
|
exp: []uint32{1, 4, 5, 6, 7, 8, 9, 10, 11, 12},
|
|
},
|
|
{
|
|
array: []uint32{},
|
|
runs: []interval32{{start: 5, last: 10}},
|
|
exp: []uint32{5, 6, 7, 8, 9, 10},
|
|
},
|
|
{
|
|
array: []uint32{1, 4, 5, 7, 10, 11, 12},
|
|
runs: []interval32{},
|
|
exp: []uint32{1, 4, 5, 7, 10, 11, 12},
|
|
},
|
|
{
|
|
array: []uint32{0, 1, 4, 5, 7, 10, 11, 12},
|
|
runs: []interval32{{start: 0, last: 5}, {start: 7, last: 7}},
|
|
exp: []uint32{0, 1, 2, 3, 4, 5, 7, 10, 11, 12},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
a.array = test.array
|
|
b.runs = test.runs
|
|
ret := unionArrayRun(a, b)
|
|
if !reflect.DeepEqual(ret.array, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBitmapSetRange(t *testing.T) {
|
|
c := &container{bitmap: make([]uint64, bitmapN)}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
start uint64
|
|
last uint64
|
|
exp []uint64
|
|
expN int
|
|
}{
|
|
{
|
|
bitmap: []uint64{0x0000000000FFF900},
|
|
start: 9,
|
|
last: 10,
|
|
exp: []uint64{0x0000000000FFFF00},
|
|
expN: 16,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFF0, 0xFF, 0xFF},
|
|
start: 60,
|
|
last: 130,
|
|
exp: []uint64{0xF000000000000FF0, 0xFFFFFFFFFFFFFFFF, 0xFF},
|
|
expN: 84,
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
c.bitmap[i] = v
|
|
}
|
|
c.n = c.countRange(0, 65535)
|
|
c.bitmapSetRange(test.start, test.last+1)
|
|
if !reflect.DeepEqual(c.bitmap[:len(test.exp)], test.exp) {
|
|
t.Fatalf("test %#v expected %x, got %x", i, test.exp, c.bitmap[:len(test.bitmap)])
|
|
}
|
|
if test.expN != c.n {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, c.n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestArrayToBitmap(t *testing.T) {
|
|
a := &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
exp []uint64
|
|
}{
|
|
{
|
|
array: []uint32{},
|
|
exp: []uint64{},
|
|
},
|
|
{
|
|
array: []uint32{0, 1, 2, 3},
|
|
exp: []uint64{0xF},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
exp := make([]uint64, bitmapN)
|
|
for i, v := range test.exp {
|
|
exp[i] = v
|
|
}
|
|
|
|
a.array = test.array
|
|
a.n = len(test.array)
|
|
a.arrayToBitmap()
|
|
if !reflect.DeepEqual(a.bitmap, exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, exp, a.bitmap)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBitmapToArray(t *testing.T) {
|
|
a := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
exp []uint32
|
|
}{
|
|
{
|
|
bitmap: []uint64{},
|
|
exp: []uint32{},
|
|
},
|
|
{
|
|
bitmap: []uint64{0xF},
|
|
exp: []uint32{0, 1, 2, 3},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.bitmap = make([]uint64, bitmapN)
|
|
n := 0
|
|
for i, v := range test.bitmap {
|
|
a.bitmap[i] = v
|
|
n += int(popcount(v))
|
|
}
|
|
a.n = n
|
|
|
|
a.bitmapToArray()
|
|
if !reflect.DeepEqual(a.array, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRunToBitmap(t *testing.T) {
|
|
a := &container{}
|
|
tests := []struct {
|
|
runs []interval32
|
|
exp []uint64
|
|
}{
|
|
{
|
|
runs: []interval32{},
|
|
exp: []uint64{},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 0}},
|
|
exp: []uint64{1},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 4}},
|
|
exp: []uint64{31},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 2, last: 2}, {start: 5, last: 7}, {start: 13, last: 14}, {start: 17, last: 17}},
|
|
exp: []uint64{155876},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 3}, {start: 60, last: 67}},
|
|
exp: []uint64{0xF00000000000000F, 0x000000000000000F},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
exp := make([]uint64, bitmapN)
|
|
n := 0
|
|
for i, v := range test.exp {
|
|
exp[i] = v
|
|
n += int(popcount(v))
|
|
}
|
|
|
|
a.runs = test.runs
|
|
a.n = n
|
|
a.runToBitmap()
|
|
if !reflect.DeepEqual(a.bitmap, exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, exp, a.bitmap)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBitmapToRun(t *testing.T) {
|
|
a := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
exp []interval32
|
|
}{
|
|
{
|
|
// empty run
|
|
bitmap: []uint64{},
|
|
exp: []interval32{},
|
|
},
|
|
{
|
|
// single-bit run
|
|
bitmap: []uint64{1},
|
|
exp: []interval32{{start: 0, last: 0}},
|
|
},
|
|
{
|
|
// single multi-bit run in one word
|
|
bitmap: []uint64{31},
|
|
exp: []interval32{{start: 0, last: 4}},
|
|
},
|
|
{
|
|
// multiple runs in one word
|
|
bitmap: []uint64{155876},
|
|
exp: []interval32{{start: 2, last: 2}, {start: 5, last: 7}, {start: 13, last: 14}, {start: 17, last: 17}},
|
|
},
|
|
{
|
|
// span two words, both mixed
|
|
bitmap: []uint64{0xF00000000000000F, 0x000000000000000F},
|
|
exp: []interval32{{start: 0, last: 3}, {start: 60, last: 67}},
|
|
},
|
|
{
|
|
// span two words, first = maxBitmap
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF, 0xF},
|
|
exp: []interval32{{start: 0, last: 67}},
|
|
},
|
|
{
|
|
// span two words, second = maxBitmap
|
|
bitmap: []uint64{0xF000000000000000, 0xFFFFFFFFFFFFFFFF},
|
|
exp: []interval32{{start: 60, last: 127}},
|
|
},
|
|
{
|
|
// span three words
|
|
bitmap: []uint64{0xF000000000000000, 0xFFFFFFFFFFFFFFFF, 0xF},
|
|
exp: []interval32{{start: 60, last: 131}},
|
|
},
|
|
{
|
|
bitmap: make([]uint64, bitmapN),
|
|
exp: []interval32{{start: 65408, last: 65535}},
|
|
},
|
|
}
|
|
tests[8].bitmap[1022] = 0xFFFFFFFFFFFFFFFF
|
|
tests[8].bitmap[1023] = 0xFFFFFFFFFFFFFFFF
|
|
|
|
for i, test := range tests {
|
|
a.bitmap = make([]uint64, bitmapN)
|
|
n := 0
|
|
for i, v := range test.bitmap {
|
|
a.bitmap[i] = v
|
|
n += int(popcount(v))
|
|
}
|
|
a.n = n
|
|
a.bitmapToRun()
|
|
if !reflect.DeepEqual(a.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestArrayToRun(t *testing.T) {
|
|
a := &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
exp []interval32
|
|
}{
|
|
{
|
|
array: []uint32{},
|
|
exp: []interval32{},
|
|
},
|
|
{
|
|
array: []uint32{0},
|
|
exp: []interval32{{start: 0, last: 0}},
|
|
},
|
|
{
|
|
array: []uint32{0, 1, 2, 3, 4},
|
|
exp: []interval32{{start: 0, last: 4}},
|
|
},
|
|
{
|
|
array: []uint32{2, 5, 6, 7, 13, 14, 17},
|
|
exp: []interval32{{start: 2, last: 2}, {start: 5, last: 7}, {start: 13, last: 14}, {start: 17, last: 17}},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
a.array = test.array
|
|
a.n = len(test.array)
|
|
a.arrayToRun()
|
|
if !reflect.DeepEqual(a.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRunToArray(t *testing.T) {
|
|
a := &container{}
|
|
tests := []struct {
|
|
runs []interval32
|
|
exp []uint32
|
|
}{
|
|
{
|
|
runs: []interval32{},
|
|
exp: []uint32{},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 0}},
|
|
exp: []uint32{0},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 4}},
|
|
exp: []uint32{0, 1, 2, 3, 4},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 2, last: 2}, {start: 5, last: 7}, {start: 13, last: 14}, {start: 17, last: 17}},
|
|
exp: []uint32{2, 5, 6, 7, 13, 14, 17},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
a.runs = test.runs
|
|
a.n = len(test.exp)
|
|
a.runToArray()
|
|
if !reflect.DeepEqual(a.array, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, a.array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBitmapZeroRange(t *testing.T) {
|
|
c := &container{bitmap: make([]uint64, bitmapN)}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
start uint64
|
|
last uint64
|
|
exp []uint64
|
|
expN int
|
|
}{
|
|
{
|
|
bitmap: []uint64{0x0000000000FFFF00},
|
|
start: 9,
|
|
last: 10,
|
|
exp: []uint64{0x0000000000FFF900},
|
|
expN: 14,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFF0, 0xFF, 0xFF},
|
|
start: 60,
|
|
last: 130,
|
|
exp: []uint64{0xFF0, 0, 0xF8},
|
|
expN: 13,
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
c.bitmap[i] = v
|
|
}
|
|
c.n = c.countRange(0, 65535)
|
|
c.bitmapZeroRange(test.start, test.last+1)
|
|
if !reflect.DeepEqual(c.bitmap[:len(test.exp)], test.exp) {
|
|
t.Fatalf("test %#v expected %x, got %x", i, test.exp, c.bitmap[:len(test.bitmap)])
|
|
}
|
|
if test.expN != c.n {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, c.n)
|
|
}
|
|
for i, _ := range test.bitmap {
|
|
c.bitmap[i] = 0
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestUnionBitmapRun(t *testing.T) {
|
|
a := &container{bitmap: make([]uint64, bitmapN)}
|
|
b := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
runs []interval32
|
|
exp []uint64
|
|
expN int
|
|
}{
|
|
{
|
|
bitmap: []uint64{2},
|
|
runs: []interval32{{start: 0, last: 0}, {start: 2, last: 5}, {start: 62, last: 71}, {start: 77, last: 78}},
|
|
exp: []uint64{0xC00000000000003F, 0x60FF},
|
|
expN: 18,
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
a.bitmap[i] = v
|
|
}
|
|
a.n = a.bitmapCountRange(0, 65535)
|
|
b.runs = test.runs
|
|
ret := unionBitmapRun(a, b)
|
|
if ret.isArray() {
|
|
ret.arrayToBitmap()
|
|
}
|
|
if !reflect.DeepEqual(ret.bitmap[:len(test.exp)], test.exp) {
|
|
t.Fatalf("test #%v expected %x, but got %x", i, test.exp, ret.bitmap[:len(test.exp)])
|
|
}
|
|
if ret.n != test.expN {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, ret.n)
|
|
}
|
|
for i, _ := range test.bitmap {
|
|
a.bitmap[i] = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBitmapCountRuns(t *testing.T) {
|
|
c := &container{bitmap: make([]uint64, bitmapN)}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
exp int
|
|
}{
|
|
{
|
|
bitmap: []uint64{0xFF00FF00},
|
|
exp: 2,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFF00FF0000000000, 0x1},
|
|
exp: 2,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFF00FF0000000000, 0x2, 0x100},
|
|
exp: 4,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xFF00FF0000000000, 0x1010101FF0101010, 0x100},
|
|
exp: 10,
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
for j, v := range test.bitmap {
|
|
c.bitmap[j] = v
|
|
}
|
|
|
|
ret := c.bitmapCountRuns()
|
|
if ret != test.exp {
|
|
t.Fatalf("test #%v expected %v but got %v", i, test.exp, ret)
|
|
}
|
|
|
|
for j, _ := range test.bitmap {
|
|
c.bitmap[j] = 0
|
|
}
|
|
}
|
|
|
|
test := tests[3]
|
|
for j, v := range test.bitmap {
|
|
c.bitmap[1024-len(test.bitmap)+j] = v
|
|
|
|
}
|
|
ret := c.bitmapCountRuns()
|
|
if ret != test.exp {
|
|
t.Fatalf("test at end expected %v but got %v", test.exp, ret)
|
|
}
|
|
}
|
|
|
|
func TestArrayCountRuns(t *testing.T) {
|
|
c := &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
exp int
|
|
}{
|
|
{
|
|
array: []uint32{},
|
|
exp: 0,
|
|
},
|
|
{
|
|
array: []uint32{0},
|
|
exp: 1,
|
|
},
|
|
{
|
|
array: []uint32{1},
|
|
exp: 1,
|
|
},
|
|
{
|
|
array: []uint32{1, 2, 3, 5},
|
|
exp: 2,
|
|
},
|
|
{
|
|
array: []uint32{0, 1, 3, 9, 2048, 4096, 4097, 65534, 65535},
|
|
exp: 6,
|
|
},
|
|
{
|
|
array: []uint32{0, 10, 11, 12},
|
|
exp: 2,
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
c.array = test.array
|
|
ret := c.arrayCountRuns()
|
|
if ret != test.exp {
|
|
t.Fatalf("test #%v expected %v but got %v", i, test.exp, ret)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDifferenceArrayRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
array []uint32
|
|
runs []interval32
|
|
exp []uint32
|
|
}{
|
|
{
|
|
array: []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
|
|
runs: []interval32{{start: 5, last: 10}},
|
|
exp: []uint32{0, 1, 2, 3, 4, 11, 12},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.array = test.array
|
|
a.n = len(a.array)
|
|
b.runs = test.runs
|
|
b.n = b.runCountRange(0, 100)
|
|
ret := differenceArrayRun(a, b)
|
|
if !reflect.DeepEqual(ret.array, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDifferenceRunArray(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
runs []interval32
|
|
array []uint32
|
|
exp []interval32
|
|
}{
|
|
{
|
|
runs: []interval32{{start: 0, last: 12}},
|
|
array: []uint32{5, 6, 7, 8, 9, 10},
|
|
exp: []interval32{{start: 0, last: 4}, {start: 11, last: 12}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 12}},
|
|
array: []uint32{0, 1, 2, 3},
|
|
exp: []interval32{{start: 4, last: 12}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 12}},
|
|
array: []uint32{9, 10, 11, 12, 13},
|
|
exp: []interval32{{start: 0, last: 8}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 1, last: 12}},
|
|
array: []uint32{0, 9, 10, 11, 12, 13},
|
|
exp: []interval32{{start: 1, last: 8}},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.runs
|
|
a.n = a.runCountRange(0, 100)
|
|
b.array = test.array
|
|
b.n = len(b.array)
|
|
ret := differenceRunArray(a, b)
|
|
if !reflect.DeepEqual(ret.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDifferenceRunBitmap(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{bitmap: make([]uint64, bitmapN)}
|
|
tests := []struct {
|
|
runs []interval32
|
|
bitmap []uint64
|
|
exp []interval32
|
|
}{
|
|
{
|
|
runs: []interval32{{start: 0, last: 63}},
|
|
bitmap: []uint64{0x0000FFFF000000F0},
|
|
exp: []interval32{{start: 0, last: 3}, {start: 8, last: 31}, {start: 48, last: 63}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 63}},
|
|
bitmap: []uint64{0x8000000000000000},
|
|
exp: []interval32{{start: 0, last: 62}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 63}},
|
|
bitmap: []uint64{0x0000000000000001},
|
|
exp: []interval32{{start: 1, last: 63}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 63}},
|
|
bitmap: []uint64{0x0, 0x0000000000000001},
|
|
exp: []interval32{{start: 0, last: 63}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 65}},
|
|
bitmap: []uint64{0x0, 0x0000000000000001},
|
|
exp: []interval32{{start: 0, last: 63}, {start: 65, last: 65}},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 65}},
|
|
bitmap: []uint64{0x0, 0x8000000000000000},
|
|
exp: []interval32{{start: 0, last: 65}},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.runs
|
|
a.n = a.runCountRange(0, 100)
|
|
for i, v := range test.bitmap {
|
|
b.bitmap[i] = v
|
|
}
|
|
b.n = b.bitmapCountRange(0, 100)
|
|
ret := differenceRunBitmap(a, b)
|
|
if !reflect.DeepEqual(ret.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDifferenceBitmapRun(t *testing.T) {
|
|
a := &container{bitmap: make([]uint64, bitmapN)}
|
|
b := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
runs []interval32
|
|
exp []uint64
|
|
}{
|
|
{
|
|
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
|
|
runs: []interval32{{start: 4, last: 7}, {start: 32, last: 47}},
|
|
exp: []uint64{0xFFFF0000FFFFFF0F},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
a.bitmap[i] = v
|
|
}
|
|
a.n = a.bitmapCountRange(0, 100)
|
|
b.runs = test.runs
|
|
b.n = b.runCountRange(0, 100)
|
|
ret := differenceBitmapRun(a, b)
|
|
if !reflect.DeepEqual(ret.bitmap[:len(test.exp)], test.exp) {
|
|
t.Fatalf("test #%v expected \n%X, but got \n%X", i, test.exp, ret.bitmap[:len(test.exp)])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDifferenceBitmapArray(t *testing.T) {
|
|
a := &container{bitmap: make([]uint64, bitmapN)}
|
|
b := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
array []uint32
|
|
exp []uint32
|
|
}{
|
|
{
|
|
bitmap: []uint64{0xFF0F},
|
|
array: []uint32{0, 1, 2, 3, 4, 5, 6, 7, 10},
|
|
exp: []uint32{8, 9, 11, 12, 13, 14, 15},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.bitmap = test.bitmap
|
|
b.array = test.array
|
|
ret := differenceBitmapArray(a, b)
|
|
if !reflect.DeepEqual(ret.array, test.exp) {
|
|
t.Fatalf("test #%v expected \n%X, but got \n%X", i, test.exp, ret.array)
|
|
}
|
|
}
|
|
}
|
|
func TestDifferenceBitmapBitmap(t *testing.T) {
|
|
a := &container{bitmap: make([]uint64, bitmapN)}
|
|
b := &container{bitmap: make([]uint64, bitmapN)}
|
|
tests := []struct {
|
|
abitmap []uint64
|
|
bbitmap []uint64
|
|
exp []uint32
|
|
}{
|
|
{
|
|
abitmap: []uint64{0xFF00FFFFFFFFFFFF},
|
|
bbitmap: []uint64{0xFFFFFFFFFFFFF000},
|
|
exp: []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
|
|
},
|
|
{
|
|
abitmap: []uint64{0xF},
|
|
bbitmap: []uint64{},
|
|
exp: []uint32{0, 1, 2, 3},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.bitmap = test.abitmap
|
|
b.bitmap = test.bbitmap
|
|
ret := differenceBitmapBitmap(a, b)
|
|
if !reflect.DeepEqual(ret.array, test.exp) {
|
|
t.Fatalf("test #%v expected \n%X, but got \n%X", i, test.exp, ret.array)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDifferenceRunRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
aruns []interval32
|
|
bruns []interval32
|
|
exp []interval32
|
|
}{
|
|
{
|
|
// this tests all six overlap combinations
|
|
// A [ ] [ ] [ ] [ ] [ ] [ ]
|
|
// B [ ] [ ] [ ] [ ] [ ] [ ]
|
|
aruns: []interval32{{start: 3, last: 6}, {start: 13, last: 16}, {start: 24, last: 26}, {start: 33, last: 38}, {start: 43, last: 46}, {start: 53, last: 56}},
|
|
bruns: []interval32{{start: 1, last: 8}, {start: 11, last: 14}, {start: 21, last: 23}, {start: 35, last: 37}, {start: 44, last: 48}, {start: 57, last: 59}},
|
|
exp: []interval32{{start: 15, last: 16}, {start: 24, last: 26}, {start: 33, last: 34}, {start: 38, last: 38}, {start: 43, last: 43}, {start: 53, last: 56}},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.aruns
|
|
a.n = a.runCountRange(0, 100)
|
|
b.runs = test.bruns
|
|
b.n = b.runCountRange(0, 100)
|
|
ret := differenceRunRun(a, b)
|
|
if !reflect.DeepEqual(ret.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWriteReadArray(t *testing.T) {
|
|
ca := &container{array: []uint32{1, 10, 100, 1000}, n: 4}
|
|
ba := &Bitmap{keys: []uint64{0}, containers: []*container{ca}}
|
|
ba2 := &Bitmap{}
|
|
var buf bytes.Buffer
|
|
_, err := ba.WriteTo(&buf)
|
|
if err != nil {
|
|
t.Fatalf("error writing: %v", err)
|
|
}
|
|
err = ba2.UnmarshalBinary(buf.Bytes())
|
|
if err != nil {
|
|
t.Fatalf("error unmarshaling: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(ba2.containers[0].array, ca.array) {
|
|
t.Fatalf("array test expected %x, but got %x", ca.array, ba2.containers[0].array)
|
|
}
|
|
}
|
|
|
|
func TestWriteReadBitmap(t *testing.T) {
|
|
// create bitmap containing > 4096 bits
|
|
cb := &container{bitmap: make([]uint64, bitmapN), n: 129 * 32}
|
|
for i := 0; i < 129; i++ {
|
|
cb.bitmap[i] = 0x5555555555555555
|
|
}
|
|
bb := &Bitmap{keys: []uint64{0}, containers: []*container{cb}}
|
|
bb2 := &Bitmap{}
|
|
var buf bytes.Buffer
|
|
_, err := bb.WriteTo(&buf)
|
|
if err != nil {
|
|
t.Fatalf("error writing: %v", err)
|
|
}
|
|
err = bb2.UnmarshalBinary(buf.Bytes())
|
|
if err != nil {
|
|
t.Fatalf("error unmarshaling: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(bb2.containers[0].bitmap, cb.bitmap) {
|
|
t.Fatalf("bitmap test expected %x, but got %x", cb.bitmap, bb2.containers[0].bitmap)
|
|
}
|
|
}
|
|
|
|
func TestWriteReadRun(t *testing.T) {
|
|
cr := &container{runs: []interval32{{start: 3, last: 13}, {start: 100, last: 109}}, n: 20}
|
|
br := &Bitmap{keys: []uint64{0}, containers: []*container{cr}}
|
|
br2 := &Bitmap{}
|
|
var buf bytes.Buffer
|
|
_, err := br.WriteTo(&buf)
|
|
if err != nil {
|
|
t.Fatalf("error writing: %v", err)
|
|
}
|
|
err = br2.UnmarshalBinary(buf.Bytes())
|
|
if err != nil {
|
|
t.Fatalf("error unmarshaling: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(br2.containers[0].runs, cr.runs) {
|
|
t.Fatalf("run test expected %x, but got %x", cr.runs, br2.containers[0].runs)
|
|
}
|
|
}
|
|
|
|
func TestXorArrayRun(t *testing.T) {
|
|
a := &container{array: []uint32{1, 5, 10, 11, 12}}
|
|
b := &container{runs: []interval32{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}}
|
|
exp := []uint32{1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 15, 16}
|
|
|
|
ret := xorArrayRun(a, b)
|
|
if !reflect.DeepEqual(ret.array, exp) {
|
|
t.Fatalf("test expected %v, but got %v", exp, ret.array)
|
|
}
|
|
}
|
|
|
|
func TestXorRunRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
aruns []interval32
|
|
bruns []interval32
|
|
exp []interval32
|
|
}{
|
|
{
|
|
aruns: []interval32{},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 5, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 4}},
|
|
bruns: []interval32{{start: 6, last: 10}},
|
|
exp: []interval32{{start: 0, last: 4}, {start: 6, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 6}},
|
|
bruns: []interval32{{start: 4, last: 10}},
|
|
exp: []interval32{{start: 0, last: 3}, {start: 7, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 4, last: 10}},
|
|
bruns: []interval32{{start: 0, last: 6}},
|
|
exp: []interval32{{start: 0, last: 3}, {start: 7, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 10}},
|
|
bruns: []interval32{{start: 0, last: 6}},
|
|
exp: []interval32{{start: 7, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 6}},
|
|
bruns: []interval32{{start: 0, last: 10}},
|
|
exp: []interval32{{start: 7, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 6}},
|
|
bruns: []interval32{{start: 0, last: 10}},
|
|
exp: []interval32{{start: 7, last: 10}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 5, last: 12}},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 11, last: 12}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 12}},
|
|
bruns: []interval32{{start: 5, last: 10}},
|
|
exp: []interval32{{start: 1, last: 3}, {start: 6, last: 6}, {start: 11, last: 12}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 12}},
|
|
bruns: []interval32{{start: 2, last: 65535}},
|
|
exp: []interval32{{start: 1, last: 1}, {start: 4, last: 4}, {start: 6, last: 6}, {start: 13, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 2, last: 65535}},
|
|
bruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 12}},
|
|
exp: []interval32{{start: 1, last: 1}, {start: 4, last: 4}, {start: 6, last: 6}, {start: 13, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 12}},
|
|
bruns: []interval32{{start: 0, last: 65535}},
|
|
exp: []interval32{{start: 0, last: 0}, {start: 4, last: 4}, {start: 6, last: 6}, {start: 13, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 0, last: 65535}},
|
|
bruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 12}},
|
|
exp: []interval32{{start: 0, last: 0}, {start: 4, last: 4}, {start: 6, last: 6}, {start: 13, last: 65535}},
|
|
},
|
|
{
|
|
aruns: []interval32{{start: 1, last: 3}, {start: 5, last: 5}, {start: 7, last: 9}, {start: 12, last: 22}},
|
|
bruns: []interval32{{start: 2, last: 8}, {start: 16, last: 27}, {start: 33, last: 34}},
|
|
exp: []interval32{{start: 1, last: 1}, {start: 4, last: 4}, {start: 6, last: 6}, {start: 9, last: 9}, {start: 12, last: 15}, {start: 23, last: 27}, {start: 33, last: 34}},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.runs = test.aruns
|
|
b.runs = test.bruns
|
|
ret := xorRunRun(a, b)
|
|
if !reflect.DeepEqual(ret.runs, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBitmapXorRange(t *testing.T) {
|
|
c := &container{bitmap: make([]uint64, bitmapN)}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
start uint64
|
|
last uint64
|
|
exp []uint64
|
|
expN int
|
|
}{
|
|
{
|
|
bitmap: []uint64{0x0000000000000000},
|
|
start: 0,
|
|
last: 2,
|
|
exp: []uint64{0x0000000000000007},
|
|
expN: 3,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xF1},
|
|
start: 4,
|
|
last: 8,
|
|
exp: []uint64{0x101},
|
|
expN: 2,
|
|
},
|
|
{
|
|
bitmap: []uint64{0xAA},
|
|
start: 0,
|
|
last: 7,
|
|
exp: []uint64{0x55},
|
|
expN: 4,
|
|
},
|
|
{
|
|
bitmap: []uint64{0x0, 0x0000000000000000, 0x0000000000000000},
|
|
start: 63,
|
|
last: 128,
|
|
exp: []uint64{0x8000000000000000, 0xFFFFFFFFFFFFFFFF, 0x000000000000001},
|
|
expN: 66,
|
|
},
|
|
{
|
|
bitmap: []uint64{0x0, 0x00000000000000FF, 0x0000000000000000},
|
|
start: 63,
|
|
last: 128,
|
|
exp: []uint64{0x8000000000000000, 0xFFFFFFFFFFFFFF00, 0x000000000000001},
|
|
expN: 58,
|
|
},
|
|
{
|
|
bitmap: []uint64{0x0, 0x0, 0x0},
|
|
start: 129,
|
|
last: 131,
|
|
exp: []uint64{0x0000000000000000, 0x0000000000000000, 0x00000000000000E},
|
|
expN: 3,
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
for i, v := range test.bitmap {
|
|
c.bitmap[i] = v
|
|
}
|
|
c.n = c.countRange(0, 65535)
|
|
c.bitmapXorRange(test.start, test.last+1)
|
|
if !reflect.DeepEqual(c.bitmap[:len(test.exp)], test.exp) {
|
|
t.Fatalf("test %#v expected %x, got %x", i, test.exp, c.bitmap[:len(test.bitmap)])
|
|
}
|
|
if test.expN != c.n {
|
|
t.Fatalf("test #%v expected n to be %v, but got %v", i, test.expN, c.n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestXorBitmapRun(t *testing.T) {
|
|
a := &container{}
|
|
b := &container{}
|
|
tests := []struct {
|
|
bitmap []uint64
|
|
runs []interval32
|
|
exp []uint64
|
|
}{
|
|
{
|
|
bitmap: []uint64{0x0, 0x0, 0x0},
|
|
runs: []interval32{{start: 129, last: 131}},
|
|
exp: []uint64{0x0, 0x0, 0x00000000000000E},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
a.bitmap = test.bitmap
|
|
b.runs = test.runs
|
|
ret := xorBitmapRun(a, b)
|
|
|
|
if !reflect.DeepEqual(ret.bitmap, test.exp) {
|
|
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.bitmap)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestIteratorArray(t *testing.T) {
|
|
// use values that span two containers
|
|
b := NewBitmap(0, 1, 10, 100, 1000, 10000, 90000, 100000)
|
|
if !b.containers[0].isArray() {
|
|
t.Fatalf("wrong container type")
|
|
}
|
|
|
|
itr := b.Iterator()
|
|
if !(itr.i == 0 && itr.j == -1) {
|
|
t.Fatalf("iterator did not zero correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(1000)
|
|
if !(itr.i == 0 && itr.j == 3) {
|
|
t.Fatalf("iterator did not seek correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(10000)
|
|
itr.Next()
|
|
val, eof := itr.Next()
|
|
if !(itr.i == 1 && itr.j == 0 && val == 90000 && !eof) {
|
|
t.Fatalf("iterator did not next correctly across containers: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(80000)
|
|
if !(itr.i == 1 && itr.j == -1) {
|
|
t.Fatalf("iterator did not seek missing value correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(100000)
|
|
if !(itr.i == 1 && itr.j == 0) {
|
|
t.Fatalf("iterator did not seek correctly in multiple containers: %v\n", itr)
|
|
}
|
|
|
|
val, eof = itr.Next()
|
|
if !(val == 100000 && !eof) {
|
|
t.Fatalf("iterator did not next correctly: %d, %v\n", val, eof)
|
|
}
|
|
|
|
val, eof = itr.Next()
|
|
if !(val == 0 && eof) {
|
|
t.Fatalf("iterator did not eof correctly: %d, %v\n", val, eof)
|
|
}
|
|
}
|
|
|
|
func TestIteratorBitmap(t *testing.T) {
|
|
// use values that span two containers
|
|
// this dataset will update to bitmap after enough Adds,
|
|
// but won't update to RLE until Optimize() is called
|
|
b := NewBitmap()
|
|
for i := uint64(61000); i < 71000; i++ {
|
|
b.Add(i)
|
|
}
|
|
for i := uint64(75000); i < 75100; i++ {
|
|
b.Add(i)
|
|
}
|
|
if !b.containers[0].isBitmap() {
|
|
t.Fatalf("wrong container type")
|
|
}
|
|
|
|
itr := b.Iterator()
|
|
if !(itr.i == 0 && itr.j == -1) {
|
|
t.Fatalf("iterator did not zero correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(65000)
|
|
if !(itr.i == 0 && itr.j == 64999) {
|
|
t.Fatalf("iterator did not seek correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(65535)
|
|
itr.Next()
|
|
val, eof := itr.Next()
|
|
if !(itr.i == 1 && itr.j == 0 && val == 65536 && !eof) {
|
|
t.Fatalf("iterator did not next correctly across containers: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(74000)
|
|
if !(itr.i == 1 && itr.j == 8463) {
|
|
t.Fatalf("iterator did not seek missing value correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(70999)
|
|
if !(itr.i == 1 && itr.j == 5462) {
|
|
t.Fatalf("iterator did not seek correctly in multiple containers: %v\n", itr)
|
|
}
|
|
|
|
val, eof = itr.Next()
|
|
if !(val == 70999 && !eof) {
|
|
t.Fatalf("iterator did not next correctly: %d, %v\n", val, eof)
|
|
}
|
|
|
|
itr.Seek(75100)
|
|
val, eof = itr.Next()
|
|
if !(val == 0 && eof) {
|
|
t.Fatalf("iterator did not eof correctly: %d, %v\n", val, eof)
|
|
}
|
|
}
|
|
|
|
func TestIteratorRuns(t *testing.T) {
|
|
b := NewBitmap(0, 1, 2, 3, 4, 5, 1000, 1001, 1002, 1003, 1004, 1005, 100000, 100001, 100002, 100003, 100004, 100005)
|
|
b.Optimize()
|
|
if !b.containers[0].isRun() {
|
|
t.Fatalf("wrong container type")
|
|
}
|
|
|
|
itr := b.Iterator()
|
|
if !(itr.i == 0 && itr.j == 0 && itr.k == -1) {
|
|
t.Fatalf("iterator did not zero correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(4)
|
|
if !(itr.i == 0 && itr.j == 0 && itr.k == 3) {
|
|
t.Fatalf("iterator did not seek correctly: %v\n", itr)
|
|
}
|
|
itr.Next()
|
|
itr.Next()
|
|
val, eof := itr.Next()
|
|
if !(val == 1000 && !eof) {
|
|
t.Fatalf("iterator did not next correctly across runs: %v, %v", val, itr)
|
|
}
|
|
itr.Next()
|
|
val, eof = itr.Next()
|
|
if !(val == 1002 && !eof) {
|
|
t.Fatalf("iterator did not next correctly within a run: %v, %v", val, itr)
|
|
}
|
|
itr.Next()
|
|
itr.Next()
|
|
itr.Next()
|
|
val, eof = itr.Next()
|
|
if !(val == 100000 && !eof) {
|
|
t.Fatalf("iterator did not next correctly across containers: %v, %v", val, itr)
|
|
}
|
|
|
|
itr.Seek(500)
|
|
if !(itr.i == 0 && itr.j == 1 && itr.k == -1) {
|
|
t.Fatalf("iterator did not seek missing value correctly: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(1004)
|
|
if !(itr.i == 0 && itr.j == 1 && itr.k == 3) {
|
|
t.Fatalf("iterator did not seek correctly in multiple runs: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(1005)
|
|
if !(itr.i == 0 && itr.j == 1 && itr.k == 4) {
|
|
t.Fatalf("iterator did not seek correctly to end of run: %v\n", itr)
|
|
}
|
|
|
|
itr.Seek(100005)
|
|
if !(itr.i == 1 && itr.j == 0 && itr.k == 4) {
|
|
t.Fatalf("iterator did not seek correctly in multiple containers: %v\n", itr)
|
|
}
|
|
|
|
val, eof = itr.Next()
|
|
val, eof = itr.Next()
|
|
if !(val == 0 && eof) {
|
|
t.Fatalf("iterator did not eof correctly: %d, %v\n", val, eof)
|
|
}
|
|
}
|
|
|
|
func TestRunBinSearchContains(t *testing.T) {
|
|
tests := []struct {
|
|
runs []interval32
|
|
index uint32
|
|
exp struct {
|
|
index int
|
|
found bool
|
|
}
|
|
}{
|
|
{
|
|
runs: []interval32{{start: 0, last: 10}},
|
|
index: uint32(3),
|
|
exp: struct {
|
|
index int
|
|
found bool
|
|
}{index: 0, found: true},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 10}},
|
|
index: uint32(13),
|
|
exp: struct {
|
|
index int
|
|
found bool
|
|
}{index: 0, found: false},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 10}, {start: 20, last: 30}},
|
|
index: uint32(13),
|
|
exp: struct {
|
|
index int
|
|
found bool
|
|
}{index: 0, found: false},
|
|
},
|
|
{
|
|
runs: []interval32{{start: 0, last: 10}, {start: 20, last: 30}},
|
|
index: uint32(36),
|
|
exp: struct {
|
|
index int
|
|
found bool
|
|
}{index: 1, found: false},
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
index := test.index
|
|
runs := test.runs
|
|
idx, found := binSearchRuns(index, runs)
|
|
|
|
if test.exp.index != idx && test.exp.found != found {
|
|
t.Fatalf("test #%v expected %v , but got %v %v", i, test.exp, idx, found)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRunBinSearch(t *testing.T) {
|
|
tests := []struct {
|
|
runs []interval32
|
|
search uint32
|
|
exp bool
|
|
expi int
|
|
}{
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 1,
|
|
exp: false,
|
|
expi: 0,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 2,
|
|
exp: true,
|
|
expi: 0,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 5,
|
|
exp: true,
|
|
expi: 0,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 10,
|
|
exp: true,
|
|
expi: 0,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 20,
|
|
exp: false,
|
|
expi: 1,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 55,
|
|
exp: true,
|
|
expi: 1,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 70,
|
|
exp: false,
|
|
expi: 2,
|
|
},
|
|
{
|
|
runs: []interval32{{2, 10}, {50, 60}, {80, 90}},
|
|
search: 100,
|
|
exp: false,
|
|
expi: 3,
|
|
},
|
|
}
|
|
for i, test := range tests {
|
|
idx, contains := runBinSearch(test.search, test.runs)
|
|
if !(test.exp == contains && test.expi == idx) {
|
|
t.Fatalf("test #%v expected (%v, %v) but got (%v, %v)", i, test.exp, test.expi, contains, idx)
|
|
}
|
|
}
|
|
}
|