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  }