github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/roaringset/binary_search_tree_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/stretchr/testify/require" 19 ) 20 21 func TestBSTRoaringSet(t *testing.T) { 22 t.Run("single key, single set entry", func(t *testing.T) { 23 bst := &BinarySearchTree{} 24 key := []byte("my-key") 25 26 bst.Insert(key, Insert{Additions: []uint64{7}}) 27 28 res, err := bst.Get(key) 29 require.Nil(t, err) 30 31 assert.False(t, res.Additions.Contains(6)) 32 assert.True(t, res.Additions.Contains(7)) 33 }) 34 35 t.Run("single key, set updated multiple times", func(t *testing.T) { 36 bst := &BinarySearchTree{} 37 key := []byte("my-key") 38 39 for i := uint64(7); i < 14; i++ { 40 bst.Insert(key, Insert{Additions: []uint64{i}}) 41 } 42 43 res, err := bst.Get(key) 44 require.Nil(t, err) 45 46 assert.False(t, res.Additions.Contains(6)) 47 for i := uint64(7); i < 14; i++ { 48 assert.True(t, res.Additions.Contains(i)) 49 } 50 assert.False(t, res.Additions.Contains(15)) 51 }) 52 53 t.Run("single key, entry added, then deleted", func(t *testing.T) { 54 bst := &BinarySearchTree{} 55 key := []byte("my-key") 56 57 for i := uint64(7); i < 11; i++ { 58 bst.Insert(key, Insert{Additions: []uint64{i}}) 59 } 60 61 bst.Insert(key, Insert{Deletions: []uint64{9}}) 62 63 res, err := bst.Get(key) 64 require.Nil(t, err) 65 66 // check Additions 67 assert.True(t, res.Additions.Contains(7)) 68 assert.True(t, res.Additions.Contains(8)) 69 assert.False(t, res.Additions.Contains(9)) 70 assert.True(t, res.Additions.Contains(10)) 71 72 // check Deletions 73 assert.True(t, res.Deletions.Contains(9)) 74 }) 75 76 t.Run("single key, entry added, then deleted, then re-added", func(t *testing.T) { 77 bst := &BinarySearchTree{} 78 key := []byte("my-key") 79 80 for i := uint64(7); i < 11; i++ { 81 bst.Insert(key, Insert{Additions: []uint64{i}}) 82 } 83 84 bst.Insert(key, Insert{Deletions: []uint64{9}}) 85 86 bst.Insert(key, Insert{Additions: []uint64{9}}) 87 88 res, err := bst.Get(key) 89 require.Nil(t, err) 90 91 // check Additions 92 assert.True(t, res.Additions.Contains(7)) 93 assert.True(t, res.Additions.Contains(8)) 94 assert.True(t, res.Additions.Contains(9)) 95 assert.True(t, res.Additions.Contains(10)) 96 97 // check Deletions 98 assert.False(t, res.Deletions.Contains(9)) 99 }) 100 101 t.Run("get is snapshot of underlying bitmaps", func(t *testing.T) { 102 bst := &BinarySearchTree{} 103 key := []byte("my-key") 104 105 for i := uint64(1); i <= 3; i++ { 106 bst.Insert(key, Insert{ 107 Additions: []uint64{10 + i}, 108 Deletions: []uint64{10 - i}, 109 }) 110 } 111 112 getBeforeUpdate, err := bst.Get(key) 113 require.Nil(t, err) 114 115 expectedAdditionsBeforeUpdate := []uint64{11, 12, 13} 116 expectedDeletionsBeforeUpdate := []uint64{7, 8, 9} 117 118 assert.ElementsMatch(t, expectedAdditionsBeforeUpdate, getBeforeUpdate.Additions.ToArray()) 119 assert.ElementsMatch(t, expectedDeletionsBeforeUpdate, getBeforeUpdate.Deletions.ToArray()) 120 121 t.Run("gotten layer does not change on bst update", func(t *testing.T) { 122 bst.Insert(key, Insert{Additions: []uint64{100}, Deletions: []uint64{1}}) 123 124 getAfterUpdate, err := bst.Get(key) 125 require.Nil(t, err) 126 127 expectedAdditionsAfterUpdate := []uint64{11, 12, 13, 100} 128 expectedDeletionsAfterUpdate := []uint64{1, 7, 8, 9} 129 130 assert.ElementsMatch(t, expectedAdditionsBeforeUpdate, getBeforeUpdate.Additions.ToArray()) 131 assert.ElementsMatch(t, expectedDeletionsBeforeUpdate, getBeforeUpdate.Deletions.ToArray()) 132 133 assert.ElementsMatch(t, expectedAdditionsAfterUpdate, getAfterUpdate.Additions.ToArray()) 134 assert.ElementsMatch(t, expectedDeletionsAfterUpdate, getAfterUpdate.Deletions.ToArray()) 135 }) 136 }) 137 } 138 139 func TestBSTRoaringSet_Flatten(t *testing.T) { 140 t.Run("flattened bst is snapshot of current bst", func(t *testing.T) { 141 key1 := "key-1" 142 key2 := "key-2" 143 key3 := "key-3" 144 145 bst := &BinarySearchTree{} 146 // mixed order 147 bst.Insert([]byte(key3), Insert{Additions: []uint64{7, 8, 9}, Deletions: []uint64{77, 88, 99}}) 148 bst.Insert([]byte(key1), Insert{Additions: []uint64{1, 2, 3}, Deletions: []uint64{11, 22, 33}}) 149 bst.Insert([]byte(key2), Insert{Additions: []uint64{4, 5, 6}, Deletions: []uint64{44, 55, 66}}) 150 151 flatBeforeUpdate := bst.FlattenInOrder() 152 153 expectedBeforeUpdate := []struct { 154 key string 155 additions []uint64 156 deletions []uint64 157 }{ 158 {key1, []uint64{1, 2, 3}, []uint64{11, 22, 33}}, 159 {key2, []uint64{4, 5, 6}, []uint64{44, 55, 66}}, 160 {key3, []uint64{7, 8, 9}, []uint64{77, 88, 99}}, 161 } 162 163 assert.Len(t, flatBeforeUpdate, len(expectedBeforeUpdate)) 164 for i, exp := range expectedBeforeUpdate { 165 assert.Equal(t, []byte(exp.key), flatBeforeUpdate[i].Key) 166 assert.ElementsMatch(t, exp.additions, flatBeforeUpdate[i].Value.Additions.ToArray()) 167 assert.ElementsMatch(t, exp.deletions, flatBeforeUpdate[i].Value.Deletions.ToArray()) 168 } 169 170 t.Run("flattened bst does not change on bst update", func(t *testing.T) { 171 key4 := "key-4" 172 173 // mixed order 174 bst.Insert([]byte(key4), Insert{Additions: []uint64{111, 222, 333}, Deletions: []uint64{444, 555, 666}}) 175 bst.Insert([]byte(key3), Insert{Additions: []uint64{77, 88}, Deletions: []uint64{7, 8}}) 176 bst.Insert([]byte(key1), Insert{Additions: []uint64{11, 22}, Deletions: []uint64{1, 2}}) 177 178 flatAfterUpdate := bst.FlattenInOrder() 179 180 expectedAfterUpdate := []struct { 181 key string 182 additions []uint64 183 deletions []uint64 184 }{ 185 {key1, []uint64{3, 11, 22}, []uint64{1, 2, 33}}, 186 {key2, []uint64{4, 5, 6}, []uint64{44, 55, 66}}, 187 {key3, []uint64{9, 77, 88}, []uint64{7, 8, 99}}, 188 {key4, []uint64{111, 222, 333}, []uint64{444, 555, 666}}, 189 } 190 191 assert.Len(t, flatBeforeUpdate, len(expectedBeforeUpdate)) 192 for i, exp := range expectedBeforeUpdate { 193 assert.Equal(t, []byte(exp.key), flatBeforeUpdate[i].Key) 194 assert.ElementsMatch(t, exp.additions, flatBeforeUpdate[i].Value.Additions.ToArray()) 195 assert.ElementsMatch(t, exp.deletions, flatBeforeUpdate[i].Value.Deletions.ToArray()) 196 } 197 198 assert.Len(t, flatAfterUpdate, len(expectedAfterUpdate)) 199 for i, exp := range expectedAfterUpdate { 200 assert.Equal(t, []byte(exp.key), flatAfterUpdate[i].Key) 201 assert.ElementsMatch(t, exp.additions, flatAfterUpdate[i].Value.Additions.ToArray()) 202 assert.ElementsMatch(t, exp.deletions, flatAfterUpdate[i].Value.Deletions.ToArray()) 203 } 204 }) 205 }) 206 }