otterscan/cmd/otter/commands/otterscan_search_backward_t...

144 lines
4.1 KiB
Go

package commands
import (
"bytes"
"testing"
"github.com/RoaringBitmap/roaring/roaring64"
)
func newMockBackwardChunkLocator(chunks [][]byte) ChunkLocator {
return func(block uint64) (ChunkProvider, bool, error) {
for i, v := range chunks {
bm := roaring64.NewBitmap()
if _, err := bm.ReadFrom(bytes.NewReader(v)); err != nil {
return nil, false, err
}
if block > bm.Maximum() {
continue
}
return newMockBackwardChunkProvider(chunks[:i+1]), true, nil
}
// Not found; return the last to simulate the behavior of returning
// everything up to the 0xffff... chunk
if len(chunks) > 0 {
return newMockBackwardChunkProvider(chunks), true, nil
}
return nil, true, nil
}
}
func newMockBackwardChunkProvider(chunks [][]byte) ChunkProvider {
i := len(chunks) - 1
return func() ([]byte, bool, error) {
if i < 0 {
return nil, false, nil
}
chunk := chunks[i]
i--
return chunk, true, nil
}
}
func TestBackwardBlockProviderWith1Chunk(t *testing.T) {
// Mocks 1 chunk
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1})
blockProvider := NewBackwardBlockProvider(chunkLocator, 0)
checkNext(t, blockProvider, 1010, true)
checkNext(t, blockProvider, 1005, true)
checkNext(t, blockProvider, 1000, false)
}
func TestBackwardBlockProviderWith1ChunkMiddleBlock(t *testing.T) {
// Mocks 1 chunk
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1})
blockProvider := NewBackwardBlockProvider(chunkLocator, 1005)
checkNext(t, blockProvider, 1005, true)
checkNext(t, blockProvider, 1000, false)
}
func TestBackwardBlockProviderWith1ChunkNotExactBlock(t *testing.T) {
// Mocks 1 chunk
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1})
blockProvider := NewBackwardBlockProvider(chunkLocator, 1003)
checkNext(t, blockProvider, 1000, false)
}
func TestBackwardBlockProviderWith1ChunkLastBlock(t *testing.T) {
// Mocks 1 chunk
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1})
blockProvider := NewBackwardBlockProvider(chunkLocator, 1000)
checkNext(t, blockProvider, 1000, false)
}
func TestBackwardBlockProviderWith1ChunkBlockNotFound(t *testing.T) {
// Mocks 1 chunk
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1})
blockProvider := NewBackwardBlockProvider(chunkLocator, 900)
checkNext(t, blockProvider, 0, false)
}
func TestBackwardBlockProviderWithNoChunks(t *testing.T) {
chunkLocator := newMockBackwardChunkLocator([][]byte{})
blockProvider := NewBackwardBlockProvider(chunkLocator, 0)
checkNext(t, blockProvider, 0, false)
}
func TestBackwardBlockProviderWithMultipleChunks(t *testing.T) {
// Mocks 2 chunks
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunk2 := createBitmap(t, []uint64{1501, 1600})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1, chunk2})
blockProvider := NewBackwardBlockProvider(chunkLocator, 0)
checkNext(t, blockProvider, 1600, true)
checkNext(t, blockProvider, 1501, true)
checkNext(t, blockProvider, 1010, true)
checkNext(t, blockProvider, 1005, true)
checkNext(t, blockProvider, 1000, false)
}
func TestBackwardBlockProviderWithMultipleChunksBlockBetweenChunks(t *testing.T) {
// Mocks 2 chunks
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunk2 := createBitmap(t, []uint64{1501, 1600})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1, chunk2})
blockProvider := NewBackwardBlockProvider(chunkLocator, 1500)
checkNext(t, blockProvider, 1010, true)
checkNext(t, blockProvider, 1005, true)
checkNext(t, blockProvider, 1000, false)
}
func TestBackwardBlockProviderWithMultipleChunksBlockNotFound(t *testing.T) {
// Mocks 2 chunks
chunk1 := createBitmap(t, []uint64{1000, 1005, 1010})
chunk2 := createBitmap(t, []uint64{1501, 1600})
chunkLocator := newMockBackwardChunkLocator([][]byte{chunk1, chunk2})
blockProvider := NewBackwardBlockProvider(chunkLocator, 900)
checkNext(t, blockProvider, 0, false)
}