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  }