github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/lsmkv/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 lsmkv
    13  
    14  import (
    15  	"crypto/rand"
    16  	"testing"
    17  
    18  	"github.com/google/uuid"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  // This test asserts that the *binarySearchTree.insert
    23  // method properly calculates the net additions of a
    24  // new node into the tree
    25  func TestInsertNetAdditions_Replace(t *testing.T) {
    26  	t.Run("single node entry", func(t *testing.T) {
    27  		tree := &binarySearchTree{}
    28  
    29  		key := make([]byte, 8)
    30  		val := make([]byte, 8)
    31  
    32  		rand.Read(key)
    33  		rand.Read(val)
    34  
    35  		n, _ := tree.insert(key, val, nil)
    36  		require.Equal(t, len(key)+len(val), n)
    37  	})
    38  
    39  	t.Run("multiple unique node entries", func(t *testing.T) {
    40  		tree := &binarySearchTree{}
    41  
    42  		amount := 100
    43  		size := 8
    44  
    45  		var n int
    46  		for i := 0; i < amount; i++ {
    47  			key := make([]byte, size)
    48  			val := make([]byte, size)
    49  
    50  			rand.Read(key)
    51  			rand.Read(val)
    52  
    53  			newAdditions, _ := tree.insert(key, val, nil)
    54  			n += newAdditions
    55  		}
    56  
    57  		require.Equal(t, amount*size*2, n)
    58  	})
    59  
    60  	t.Run("multiple non-unique node entries", func(t *testing.T) {
    61  		tree := &binarySearchTree{}
    62  
    63  		var (
    64  			amount      = 100
    65  			keySize     = 100
    66  			origValSize = 100
    67  			newValSize  = origValSize * 100
    68  			keys        = make([][]byte, amount)
    69  			vals        = make([][]byte, amount)
    70  
    71  			netAdditions int
    72  		)
    73  
    74  		// write the keys and original values
    75  		for i := range keys {
    76  			key := make([]byte, keySize)
    77  			rand.Read(key)
    78  
    79  			val := make([]byte, origValSize)
    80  			rand.Read(val)
    81  
    82  			keys[i], vals[i] = key, val
    83  		}
    84  
    85  		// make initial inserts
    86  		for i := range keys {
    87  			currentNetAddition, _ := tree.insert(keys[i], vals[i], nil)
    88  			netAdditions += currentNetAddition
    89  		}
    90  
    91  		// change the values of the existing keys
    92  		// with new values of different length
    93  		for i := 0; i < amount; i++ {
    94  			val := make([]byte, newValSize)
    95  			rand.Read(val)
    96  
    97  			vals[i] = val
    98  		}
    99  
   100  		for i := 0; i < amount; i++ {
   101  			currentNetAddition, _ := tree.insert(keys[i], vals[i], nil)
   102  			netAdditions += currentNetAddition
   103  		}
   104  
   105  		// Formulas for calculating the total net additions after
   106  		// updating the keys with differently sized values
   107  		expectedFirstNetAdd := amount * (keySize + origValSize)
   108  		expectedSecondNetAdd := (amount * (keySize + newValSize)) - (amount * keySize) - (amount * origValSize)
   109  		expectedNetAdditions := expectedFirstNetAdd + expectedSecondNetAdd
   110  
   111  		require.Equal(t, expectedNetAdditions, netAdditions)
   112  	})
   113  
   114  	// test to assure multiple tombstone nodes are not created when same value is added and deleted multiple times
   115  	// https://semi-technology.atlassian.net/browse/WEAVIATE-31
   116  	t.Run("consecutive adding and deleting value does not multiply nodes", func(t *testing.T) {
   117  		tree := &binarySearchTree{}
   118  
   119  		key := []byte(uuid.New().String())
   120  		value := make([]byte, 100)
   121  		rand.Read(value)
   122  
   123  		for i := 0; i < 10; i++ {
   124  			tree.insert(key, value, nil)
   125  			tree.setTombstone(key, nil)
   126  		}
   127  
   128  		flat := tree.flattenInOrder()
   129  
   130  		require.Equal(t, 1, len(flat))
   131  		require.True(t, flat[0].tombstone)
   132  	})
   133  }