github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/vector/hnsw/vertex_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 hnsw
    13  
    14  import (
    15  	"testing"
    16  
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestVertex_SetConnections(t *testing.T) {
    21  	type test struct {
    22  		name        string
    23  		initial     []uint64
    24  		updated     []uint64
    25  		expectedCap int
    26  	}
    27  
    28  	tests := []test{
    29  		{
    30  			name:        "no connections set before",
    31  			initial:     nil,
    32  			updated:     makeConnections(7, 7),
    33  			expectedCap: 7,
    34  		},
    35  		{
    36  			name:    "connections had a slightly higher cap before",
    37  			initial: makeConnections(24, 24),
    38  			updated: makeConnections(22, 22),
    39  			// we don't expect any downsizing, since it's a small diff
    40  			expectedCap: 24,
    41  		},
    42  		{
    43  			name:    "connections had a considerably higher cap before",
    44  			initial: makeConnections(24, 24),
    45  			updated: makeConnections(10, 10),
    46  			// large diff, we expect downsizing
    47  			expectedCap: 10,
    48  		},
    49  		{
    50  			name:        "connections had a lower cap before",
    51  			initial:     makeConnections(10, 10),
    52  			updated:     makeConnections(24, 24),
    53  			expectedCap: 24,
    54  		},
    55  		{
    56  			name:        "connections had the same length and cap",
    57  			initial:     makeConnections(13, 13),
    58  			updated:     makeConnections(13, 13),
    59  			expectedCap: 13,
    60  		},
    61  	}
    62  
    63  	for _, tc := range tests {
    64  		t.Run(tc.name, func(t *testing.T) {
    65  			v := &vertex{
    66  				connections: make([][]uint64, 1),
    67  			}
    68  			v.connections[0] = tc.initial
    69  
    70  			v.setConnectionsAtLevel(0, tc.updated)
    71  
    72  			assert.Equal(t, tc.updated, v.connections[0])
    73  			assert.Equal(t, tc.expectedCap, cap(v.connections[0]))
    74  		})
    75  	}
    76  }
    77  
    78  func TestVertex_AppendConnection(t *testing.T) {
    79  	type test struct {
    80  		name        string
    81  		initial     []uint64
    82  		expectedCap int
    83  	}
    84  
    85  	tests := []test{
    86  		{
    87  			name:        "no connections set before, expect 1/4 of max",
    88  			initial:     nil,
    89  			expectedCap: 16,
    90  		},
    91  		{
    92  			name:        "less than 1/4, expect 1/4 of max",
    93  			initial:     makeConnections(15, 15),
    94  			expectedCap: 16,
    95  		},
    96  		{
    97  			name:        "less than 1/2, expect 1/2 of max",
    98  			initial:     makeConnections(31, 31),
    99  			expectedCap: 32,
   100  		},
   101  		{
   102  			name:        "less than 3/4, expect 3/4 of max",
   103  			initial:     makeConnections(42, 42),
   104  			expectedCap: 48,
   105  		},
   106  		{
   107  			name:        "more than 3/4, expect full size",
   108  			initial:     makeConnections(53, 53),
   109  			expectedCap: 64,
   110  		},
   111  		{
   112  			name:        "enough capacity to not require growing",
   113  			initial:     makeConnections(17, 53),
   114  			expectedCap: 53,
   115  		},
   116  	}
   117  
   118  	for _, tc := range tests {
   119  		t.Run(tc.name, func(t *testing.T) {
   120  			v := &vertex{
   121  				connections: make([][]uint64, 1),
   122  			}
   123  			v.connections[0] = tc.initial
   124  
   125  			v.appendConnectionAtLevelNoLock(0, 18, 64)
   126  
   127  			newConns := make([]uint64, len(tc.initial)+1)
   128  			copy(newConns, tc.initial)
   129  			newConns[len(newConns)-1] = 18
   130  
   131  			assert.Equal(t, newConns, v.connectionsAtLevelNoLock(0))
   132  			assert.Equal(t, tc.expectedCap, cap(v.connections[0]))
   133  		})
   134  	}
   135  }
   136  
   137  func TestVertex_AppendConnection_NotCleanlyDivisible(t *testing.T) {
   138  	type test struct {
   139  		name        string
   140  		initial     []uint64
   141  		expectedCap int
   142  	}
   143  
   144  	tests := []test{
   145  		{
   146  			name:        "no connections set before, expect 1/4 of max",
   147  			initial:     nil,
   148  			expectedCap: 15,
   149  		},
   150  		{
   151  			name:    "less than 1/4, expect 1/4 of max",
   152  			initial: makeConnections(15, 15),
   153  			// provoke rounding error
   154  			expectedCap: 16,
   155  		},
   156  		{
   157  			name:        "less than 1/2, expect 1/2 of max",
   158  			initial:     makeConnections(31, 31),
   159  			expectedCap: 32,
   160  		},
   161  		{
   162  			name:        "less than 3/4, expect 3/4 of max",
   163  			initial:     makeConnections(42, 42),
   164  			expectedCap: 47,
   165  		},
   166  		{
   167  			name:        "more than 3/4, expect full size",
   168  			initial:     makeConnections(53, 53),
   169  			expectedCap: 63,
   170  		},
   171  		{
   172  			name:        "enough capacity to not require growing",
   173  			initial:     makeConnections(17, 53),
   174  			expectedCap: 53,
   175  		},
   176  	}
   177  
   178  	for _, tc := range tests {
   179  		t.Run(tc.name, func(t *testing.T) {
   180  			v := &vertex{
   181  				connections: make([][]uint64, 1),
   182  			}
   183  			v.connections[0] = tc.initial
   184  
   185  			v.appendConnectionAtLevelNoLock(0, 18, 63)
   186  
   187  			newConns := make([]uint64, len(tc.initial)+1)
   188  			copy(newConns, tc.initial)
   189  			newConns[len(newConns)-1] = 18
   190  
   191  			assert.Equal(t, newConns, v.connectionsAtLevelNoLock(0))
   192  			assert.Equal(t, tc.expectedCap, cap(v.connections[0]))
   193  		})
   194  	}
   195  }
   196  
   197  func TestVertex_ResetConnections(t *testing.T) {
   198  	v := &vertex{
   199  		connections: make([][]uint64, 1),
   200  	}
   201  	v.connections[0] = makeConnections(4, 4)
   202  
   203  	v.resetConnectionsAtLevelNoLock(0)
   204  	assert.Equal(t, 0, len(v.connections[0]))
   205  	assert.Equal(t, 4, cap(v.connections[0]))
   206  }
   207  
   208  func makeConnections(length, capacity int) []uint64 {
   209  	out := make([]uint64, length, capacity)
   210  	for i := 0; i < length; i++ {
   211  		out[i] = uint64(i)
   212  	}
   213  	return out
   214  }
   215  
   216  func TestVertex_Maintenance(t *testing.T) {
   217  	v := &vertex{}
   218  
   219  	assert.False(t, v.isUnderMaintenance())
   220  	v.markAsMaintenance()
   221  	assert.True(t, v.isUnderMaintenance())
   222  	v.unmarkAsMaintenance()
   223  	assert.False(t, v.isUnderMaintenance())
   224  }