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 }