github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/roaringset/binary_search_tree_cursor_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package roaringset 13 14 import ( 15 "testing" 16 17 "github.com/stretchr/testify/assert" 18 "github.com/weaviate/weaviate/entities/lsmkv" 19 ) 20 21 func TestBSTCursor(t *testing.T) { 22 bst := &BinarySearchTree{} 23 24 in := []struct { 25 key string 26 addVal uint64 27 delVal uint64 28 }{ 29 {"aaa", 1, 11}, 30 {"bbb", 2, 22}, 31 {"ccc", 3, 33}, 32 {"ddd", 4, 44}, 33 } 34 35 for _, v := range in { 36 bst.Insert([]byte(v.key), Insert{Additions: []uint64{v.addVal}, Deletions: []uint64{v.delVal}}) 37 } 38 39 t.Run("start from beginning", func(t *testing.T) { 40 cursor := NewBinarySearchTreeCursor(bst) 41 42 key, layer, err := cursor.First() 43 44 assert.Equal(t, []byte(in[0].key), key) 45 assert.Equal(t, 1, layer.Additions.GetCardinality()) 46 assert.True(t, layer.Additions.Contains(in[0].addVal)) 47 assert.Equal(t, 1, layer.Deletions.GetCardinality()) 48 assert.True(t, layer.Deletions.Contains(in[0].delVal)) 49 assert.Nil(t, err) 50 }) 51 52 t.Run("start from beginning and go through all", func(t *testing.T) { 53 cursor := NewBinarySearchTreeCursor(bst) 54 55 i := 0 // 1st match is "aaa" 56 for key, layer, err := cursor.First(); key != nil; key, layer, err = cursor.Next() { 57 assert.Equal(t, []byte(in[i].key), key) 58 assert.Equal(t, 1, layer.Additions.GetCardinality()) 59 assert.True(t, layer.Additions.Contains(in[i].addVal)) 60 assert.Equal(t, 1, layer.Deletions.GetCardinality()) 61 assert.True(t, layer.Deletions.Contains(in[i].delVal)) 62 assert.Nil(t, err) 63 i++ 64 } 65 assert.Equal(t, i, len(in)) 66 }) 67 68 t.Run("seek matching element and go through rest", func(t *testing.T) { 69 cursor := NewBinarySearchTreeCursor(bst) 70 71 i := 1 // 1st match is "bbb" 72 matching := []byte("bbb") 73 for key, layer, err := cursor.Seek(matching); key != nil; key, layer, err = cursor.Next() { 74 assert.Equal(t, []byte(in[i].key), key) 75 assert.Equal(t, 1, layer.Additions.GetCardinality()) 76 assert.True(t, layer.Additions.Contains(in[i].addVal)) 77 assert.Equal(t, 1, layer.Deletions.GetCardinality()) 78 assert.True(t, layer.Deletions.Contains(in[i].delVal)) 79 assert.Nil(t, err) 80 i++ 81 } 82 assert.Equal(t, i, len(in)) 83 }) 84 85 t.Run("seek non-matching element and go through rest", func(t *testing.T) { 86 cursor := NewBinarySearchTreeCursor(bst) 87 88 i := 2 // 1st match is "ccc" 89 nonMatching := []byte("bcde") 90 for key, layer, err := cursor.Seek(nonMatching); key != nil; key, layer, err = cursor.Next() { 91 assert.Equal(t, []byte(in[i].key), key) 92 assert.Equal(t, 1, layer.Additions.GetCardinality()) 93 assert.True(t, layer.Additions.Contains(in[i].addVal)) 94 assert.Equal(t, 1, layer.Deletions.GetCardinality()) 95 assert.True(t, layer.Deletions.Contains(in[i].delVal)) 96 assert.Nil(t, err) 97 i++ 98 } 99 assert.Equal(t, i, len(in)) 100 }) 101 102 t.Run("seek missing element", func(t *testing.T) { 103 cursor := NewBinarySearchTreeCursor(bst) 104 105 missing := []byte("eee") 106 key, layer, err := cursor.Seek(missing) 107 108 assert.Nil(t, key) 109 assert.True(t, layer.Additions.IsEmpty()) 110 assert.True(t, layer.Deletions.IsEmpty()) 111 assert.ErrorIs(t, err, lsmkv.NotFound) 112 }) 113 114 t.Run("next after seek missing element does not change cursor's position", func(t *testing.T) { 115 cursor := NewBinarySearchTreeCursor(bst) 116 117 key1, _, err1 := cursor.First() 118 119 missing := []byte("eee") 120 cursor.Seek(missing) 121 122 key2, _, err2 := cursor.Next() 123 124 assert.Equal(t, []byte("aaa"), key1) 125 assert.Nil(t, err1) 126 assert.Equal(t, []byte("bbb"), key2) 127 assert.Nil(t, err2) 128 }) 129 130 t.Run("next after last is nil/empty", func(t *testing.T) { 131 cursor := NewBinarySearchTreeCursor(bst) 132 133 last := []byte("ddd") 134 cursor.Seek(last) 135 key, layer, err := cursor.Next() 136 137 assert.Nil(t, key) 138 assert.True(t, layer.Additions.IsEmpty()) 139 assert.True(t, layer.Deletions.IsEmpty()) 140 assert.Nil(t, err) 141 }) 142 143 t.Run("first after final/empty next", func(t *testing.T) { 144 cursor := NewBinarySearchTreeCursor(bst) 145 146 last := []byte("ddd") 147 cursor.Seek(last) 148 cursor.Next() 149 key, layer, err := cursor.First() 150 151 assert.Equal(t, []byte(in[0].key), key) 152 assert.Equal(t, 1, layer.Additions.GetCardinality()) 153 assert.True(t, layer.Additions.Contains(in[0].addVal)) 154 assert.Equal(t, 1, layer.Deletions.GetCardinality()) 155 assert.True(t, layer.Deletions.Contains(in[0].delVal)) 156 assert.Nil(t, err) 157 }) 158 159 t.Run("seek after final/empty next", func(t *testing.T) { 160 cursor := NewBinarySearchTreeCursor(bst) 161 162 last := []byte("ddd") 163 matching := []byte("bbb") 164 cursor.Seek(last) 165 cursor.Next() 166 key, layer, err := cursor.Seek(matching) 167 168 assert.Equal(t, []byte(in[1].key), key) 169 assert.Equal(t, 1, layer.Additions.GetCardinality()) 170 assert.True(t, layer.Additions.Contains(in[1].addVal)) 171 assert.Equal(t, 1, layer.Deletions.GetCardinality()) 172 assert.True(t, layer.Deletions.Contains(in[1].delVal)) 173 assert.Nil(t, err) 174 }) 175 }