github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/stores/tsdb/index/chunk_test.go (about) 1 package index 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 ) 9 10 // Test all sort variants 11 func TestChunkMetasSort(t *testing.T) { 12 for _, tc := range []struct { 13 desc string 14 a, b ChunkMeta 15 }{ 16 { 17 desc: "prefer mintime", 18 a: ChunkMeta{ 19 MinTime: 0, 20 MaxTime: 5, 21 }, 22 b: ChunkMeta{ 23 MinTime: 1, 24 MaxTime: 4, 25 }, 26 }, 27 { 28 desc: "delegate maxtime", 29 a: ChunkMeta{ 30 MaxTime: 2, 31 Checksum: 2, 32 }, 33 b: ChunkMeta{ 34 MaxTime: 3, 35 Checksum: 1, 36 }, 37 }, 38 { 39 desc: "delegate checksum", 40 a: ChunkMeta{ 41 Checksum: 1, 42 }, 43 b: ChunkMeta{ 44 Checksum: 2, 45 }, 46 }, 47 } { 48 t.Run(tc.desc, func(t *testing.T) { 49 xs := ChunkMetas{tc.a, tc.b} 50 require.Equal(t, true, xs.Less(0, 1)) 51 require.Equal(t, false, xs.Less(1, 0)) 52 }) 53 } 54 } 55 56 func TestChunkMetasFinalize(t *testing.T) { 57 mkMeta := func(x int) ChunkMeta { 58 return ChunkMeta{ 59 MinTime: int64(x), 60 Checksum: uint32(x), 61 } 62 } 63 for _, tc := range []struct { 64 desc string 65 input, output ChunkMetas 66 }{ 67 { 68 desc: "reorder", 69 input: []ChunkMeta{ 70 mkMeta(2), 71 mkMeta(1), 72 mkMeta(3), 73 }, 74 output: []ChunkMeta{ 75 mkMeta(1), 76 mkMeta(2), 77 mkMeta(3), 78 }, 79 }, 80 { 81 desc: "remove duplicates", 82 input: []ChunkMeta{ 83 mkMeta(1), 84 mkMeta(2), 85 mkMeta(2), 86 mkMeta(3), 87 }, 88 output: []ChunkMeta{ 89 mkMeta(1), 90 mkMeta(2), 91 mkMeta(3), 92 }, 93 }, 94 { 95 desc: "remove trailing duplicates", 96 input: []ChunkMeta{ 97 mkMeta(1), 98 mkMeta(2), 99 mkMeta(2), 100 mkMeta(3), 101 mkMeta(4), 102 mkMeta(4), 103 mkMeta(5), 104 mkMeta(5), 105 }, 106 output: []ChunkMeta{ 107 mkMeta(1), 108 mkMeta(2), 109 mkMeta(3), 110 mkMeta(4), 111 mkMeta(5), 112 }, 113 }, 114 { 115 desc: "cleanup after last duplicate", 116 input: []ChunkMeta{ 117 mkMeta(1), 118 mkMeta(2), 119 mkMeta(2), 120 mkMeta(3), 121 mkMeta(4), 122 mkMeta(5), 123 mkMeta(5), 124 mkMeta(6), 125 mkMeta(7), 126 }, 127 output: []ChunkMeta{ 128 mkMeta(1), 129 mkMeta(2), 130 mkMeta(3), 131 mkMeta(4), 132 mkMeta(5), 133 mkMeta(6), 134 mkMeta(7), 135 }, 136 }, 137 } { 138 t.Run(tc.desc, func(t *testing.T) { 139 require.Equal(t, tc.output, tc.input.Finalize()) 140 }) 141 } 142 } 143 144 func TestChunkMetas_Add(t *testing.T) { 145 chunkMetas := ChunkMetas{ 146 { 147 MinTime: 1, 148 MaxTime: 1, 149 Checksum: 1, 150 }, 151 { 152 MinTime: 2, 153 MaxTime: 3, 154 Checksum: 1, 155 }, 156 { 157 MinTime: 4, 158 MaxTime: 5, 159 Checksum: 1, 160 }, 161 { 162 MinTime: 4, 163 MaxTime: 6, 164 Checksum: 1, 165 }, 166 { 167 MinTime: 4, 168 MaxTime: 6, 169 Checksum: 2, 170 }, 171 }.Finalize() 172 173 for i, tc := range []struct { 174 chunkMetas ChunkMetas 175 toAdd ChunkMeta 176 expectedPos int 177 }{ 178 // no existing chunks 179 { 180 chunkMetas: ChunkMetas{}, 181 toAdd: ChunkMeta{MinTime: 0}, 182 }, 183 // add to the beginning 184 { 185 chunkMetas: chunkMetas, 186 toAdd: ChunkMeta{MinTime: 0}, 187 }, 188 { 189 chunkMetas: chunkMetas, 190 toAdd: ChunkMeta{ 191 MinTime: 1, 192 MaxTime: 1, 193 Checksum: 0, 194 }, 195 }, 196 // add in between 197 { 198 chunkMetas: chunkMetas, 199 toAdd: ChunkMeta{ 200 MinTime: 2, 201 MaxTime: 2, 202 }, 203 expectedPos: 1, 204 }, 205 { 206 chunkMetas: chunkMetas, 207 toAdd: ChunkMeta{ 208 MinTime: 3, 209 MaxTime: 5, 210 Checksum: 1, 211 }, 212 expectedPos: 2, 213 }, 214 { 215 chunkMetas: chunkMetas, 216 toAdd: ChunkMeta{ 217 MinTime: 4, 218 MaxTime: 4, 219 Checksum: 1, 220 }, 221 expectedPos: 2, 222 }, 223 { 224 chunkMetas: chunkMetas, 225 toAdd: ChunkMeta{ 226 MinTime: 4, 227 MaxTime: 5, 228 Checksum: 0, 229 }, 230 expectedPos: 2, 231 }, 232 // add to the end 233 { 234 chunkMetas: chunkMetas, 235 toAdd: ChunkMeta{ 236 MinTime: 5, 237 MaxTime: 6, 238 Checksum: 2, 239 }, 240 expectedPos: 5, 241 }, 242 { 243 chunkMetas: chunkMetas, 244 toAdd: ChunkMeta{ 245 MinTime: 4, 246 MaxTime: 7, 247 Checksum: 2, 248 }, 249 expectedPos: 5, 250 }, 251 { 252 chunkMetas: chunkMetas, 253 toAdd: ChunkMeta{ 254 MinTime: 4, 255 MaxTime: 6, 256 Checksum: 3, 257 }, 258 expectedPos: 5, 259 }, 260 // chunk already exists 261 { 262 chunkMetas: chunkMetas, 263 toAdd: ChunkMeta{ 264 MinTime: 4, 265 MaxTime: 6, 266 Checksum: 2, 267 }, 268 expectedPos: 4, 269 }, 270 } { 271 t.Run(fmt.Sprint(i), func(t *testing.T) { 272 chunkMetasCopy := make(ChunkMetas, len(tc.chunkMetas)) 273 copy(chunkMetasCopy, tc.chunkMetas) 274 chunkMetasCopy = append(chunkMetasCopy, tc.toAdd) 275 276 chunkMetas := tc.chunkMetas.Add(tc.toAdd) 277 require.Equal(t, chunkMetasCopy.Finalize(), chunkMetas) 278 require.Equal(t, tc.toAdd, chunkMetas[tc.expectedPos]) 279 }) 280 } 281 } 282 283 func TestChunkMetas_Drop(t *testing.T) { 284 chunkMetas := ChunkMetas{ 285 { 286 MinTime: 1, 287 MaxTime: 1, 288 Checksum: 1, 289 }, 290 { 291 MinTime: 2, 292 MaxTime: 3, 293 Checksum: 1, 294 }, 295 { 296 MinTime: 4, 297 MaxTime: 5, 298 Checksum: 1, 299 }, 300 { 301 MinTime: 4, 302 MaxTime: 6, 303 Checksum: 1, 304 }, 305 { 306 MinTime: 4, 307 MaxTime: 6, 308 Checksum: 2, 309 }, 310 }.Finalize() 311 312 // dropChunkMeta makes a copy of ChunkMetas and drops the element at index i 313 dropChunkMeta := func(i int) ChunkMetas { 314 chunkMetasCopy := make(ChunkMetas, len(chunkMetas)) 315 copy(chunkMetasCopy, chunkMetas) 316 317 return append(chunkMetasCopy[:i], chunkMetasCopy[i+1:]...) 318 } 319 320 for i, tc := range []struct { 321 chunkMetas ChunkMetas 322 toDrop ChunkMeta 323 expectedChunkMetas ChunkMetas 324 expectedChunkFound bool 325 }{ 326 // no existing chunk 327 { 328 chunkMetas: ChunkMetas{}, 329 toDrop: ChunkMeta{MinTime: 0}, 330 expectedChunkMetas: ChunkMetas{}, 331 }, 332 // drop the first chunk 333 { 334 chunkMetas: chunkMetas, 335 toDrop: chunkMetas[0], 336 expectedChunkMetas: dropChunkMeta(0), 337 expectedChunkFound: true, 338 }, 339 // drop in between 340 { 341 chunkMetas: chunkMetas, 342 toDrop: chunkMetas[1], 343 expectedChunkMetas: dropChunkMeta(1), 344 expectedChunkFound: true, 345 }, 346 { 347 chunkMetas: chunkMetas, 348 toDrop: chunkMetas[2], 349 expectedChunkMetas: dropChunkMeta(2), 350 expectedChunkFound: true, 351 }, 352 // drop from the end 353 { 354 chunkMetas: chunkMetas, 355 toDrop: chunkMetas[len(chunkMetas)-1], 356 expectedChunkMetas: dropChunkMeta(len(chunkMetas) - 1), 357 expectedChunkFound: true, 358 }, 359 } { 360 t.Run(fmt.Sprint(i), func(t *testing.T) { 361 chunkMetasCopy := make(ChunkMetas, len(tc.chunkMetas)) 362 copy(chunkMetasCopy, tc.chunkMetas) 363 364 chunkMetasCopy, chunkFound := chunkMetasCopy.Drop(tc.toDrop) 365 require.Equal(t, tc.expectedChunkFound, chunkFound) 366 require.Equal(t, tc.expectedChunkMetas, chunkMetasCopy) 367 }) 368 } 369 }