github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/get_iter_test.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble and Bitalostored Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package bitalostable 6 7 import ( 8 "strings" 9 "testing" 10 11 "github.com/cockroachdb/errors" 12 "github.com/zuoyebang/bitalostable/internal/base" 13 "github.com/zuoyebang/bitalostable/internal/keyspan" 14 "github.com/zuoyebang/bitalostable/internal/manifest" 15 "github.com/zuoyebang/bitalostable/internal/testkeys" 16 ) 17 18 func TestGetIter(t *testing.T) { 19 // testTable is a table to insert into a version. 20 // Each element of data is a string of the form "internalKey value". 21 type testTable struct { 22 level int 23 fileNum FileNum 24 data []string 25 } 26 27 testCases := []struct { 28 description string 29 // badOrdering is whether this test case has a table ordering violation. 30 badOrdering bool 31 // tables are the tables to populate the version with. 32 tables []testTable 33 // queries are the queries to run against the version. Each element has 34 // the form "internalKey wantedValue". The internalKey is passed to the 35 // version.get method, wantedValue may be "ErrNotFound" if the query 36 // should return that error. 37 queries []string 38 }{ 39 { 40 description: "empty: an empty version", 41 queries: []string{ 42 "abc.SEPARATOR.101 ErrNotFound", 43 }, 44 }, 45 46 { 47 description: "single-0: one level-0 table", 48 tables: []testTable{ 49 { 50 level: 0, 51 fileNum: 10, 52 data: []string{ 53 "the.SET.101 a", 54 "cat.SET.102 b", 55 "on_.SET.103 c", 56 "the.SET.104 d", 57 "mat.SET.105 e", 58 "the.DEL.106 ", 59 "the.MERGE.107 g", 60 }, 61 }, 62 }, 63 queries: []string{ 64 "aaa.SEPARATOR.105 ErrNotFound", 65 "cat.SEPARATOR.105 b", 66 "hat.SEPARATOR.105 ErrNotFound", 67 "mat.SEPARATOR.105 e", 68 "the.SEPARATOR.108 g", 69 "the.SEPARATOR.107 g", 70 "the.SEPARATOR.106 ErrNotFound", 71 "the.SEPARATOR.105 d", 72 "the.SEPARATOR.104 d", 73 "the.SEPARATOR.104 d", 74 "the.SEPARATOR.103 a", 75 "the.SEPARATOR.102 a", 76 "the.SEPARATOR.101 a", 77 "the.SEPARATOR.100 ErrNotFound", 78 "zzz.SEPARATOR.105 ErrNotFound", 79 }, 80 }, 81 82 { 83 description: "triple-0: three level-0 tables", 84 tables: []testTable{ 85 { 86 level: 0, 87 fileNum: 10, 88 data: []string{ 89 "the.SET.101 a", 90 "cat.SET.102 b", 91 "on_.SET.103 c", 92 "the.SET.104 d", 93 "mat.SET.105 e", 94 "the.DEL.106 ", 95 "the.SET.107 g", 96 }, 97 }, 98 { 99 level: 0, 100 fileNum: 11, 101 data: []string{ 102 "awk.SET.111 w", 103 "cat.SET.112 x", 104 "man.SET.113 y", 105 "sed.SET.114 z", 106 }, 107 }, 108 { 109 level: 0, 110 fileNum: 12, 111 data: []string{ 112 "the.DEL.121 ", 113 "cat.DEL.122 ", 114 "man.DEL.123 ", 115 "was.SET.124 D", 116 "not.SET.125 E", 117 "the.SET.126 F", 118 "man.SET.127 G", 119 }, 120 }, 121 }, 122 queries: []string{ 123 "aaa.SEPARATOR.105 ErrNotFound", 124 "awk.SEPARATOR.135 w", 125 "awk.SEPARATOR.125 w", 126 "awk.SEPARATOR.115 w", 127 "awk.SEPARATOR.105 ErrNotFound", 128 "cat.SEPARATOR.135 ErrNotFound", 129 "cat.SEPARATOR.125 ErrNotFound", 130 "cat.SEPARATOR.115 x", 131 "cat.SEPARATOR.105 b", 132 "man.SEPARATOR.135 G", 133 "man.SEPARATOR.125 ErrNotFound", 134 "man.SEPARATOR.115 y", 135 "man.SEPARATOR.105 ErrNotFound", 136 "on_.SEPARATOR.135 c", 137 "on_.SEPARATOR.125 c", 138 "on_.SEPARATOR.115 c", 139 "on_.SEPARATOR.105 c", 140 "the.SEPARATOR.135 F", 141 "the.SEPARATOR.127 F", 142 "the.SEPARATOR.126 F", 143 "the.SEPARATOR.125 ErrNotFound", 144 "the.SEPARATOR.122 ErrNotFound", 145 "the.SEPARATOR.121 ErrNotFound", 146 "the.SEPARATOR.120 g", 147 "the.SEPARATOR.115 g", 148 "the.SEPARATOR.114 g", 149 "the.SEPARATOR.111 g", 150 "the.SEPARATOR.110 g", 151 "the.SEPARATOR.108 g", 152 "the.SEPARATOR.107 g", 153 "the.SEPARATOR.106 ErrNotFound", 154 "the.SEPARATOR.105 d", 155 "the.SEPARATOR.104 d", 156 "the.SEPARATOR.104 d", 157 "the.SEPARATOR.103 a", 158 "the.SEPARATOR.102 a", 159 "the.SEPARATOR.101 a", 160 "the.SEPARATOR.100 ErrNotFound", 161 "zzz.SEPARATOR.105 ErrNotFound", 162 }, 163 }, 164 165 { 166 description: "quad-4: four level-4 tables", 167 tables: []testTable{ 168 { 169 level: 4, 170 fileNum: 11, 171 data: []string{ 172 "aardvark.SET.101 a1", 173 "alpaca__.SET.201 a2", 174 "anteater.SET.301 a3", 175 }, 176 }, 177 { 178 level: 4, 179 fileNum: 22, 180 data: []string{ 181 "baboon__.SET.102 b1", 182 "baboon__.DEL.202 ", 183 "baboon__.SET.302 b3", 184 "bear____.SET.402 b4", 185 "bear____.DEL.502 ", 186 "buffalo_.SET.602 b6", 187 }, 188 }, 189 { 190 level: 4, 191 fileNum: 33, 192 data: []string{ 193 "buffalo_.SET.103 B1", 194 }, 195 }, 196 { 197 level: 4, 198 fileNum: 44, 199 data: []string{ 200 "chipmunk.SET.104 c1", 201 "chipmunk.SET.204 c2", 202 }, 203 }, 204 }, 205 queries: []string{ 206 "a_______.SEPARATOR.999 ErrNotFound", 207 "aardvark.SEPARATOR.999 a1", 208 "aardvark.SEPARATOR.102 a1", 209 "aardvark.SEPARATOR.101 a1", 210 "aardvark.SEPARATOR.100 ErrNotFound", 211 "alpaca__.SEPARATOR.999 a2", 212 "alpaca__.SEPARATOR.200 ErrNotFound", 213 "anteater.SEPARATOR.999 a3", 214 "anteater.SEPARATOR.302 a3", 215 "anteater.SEPARATOR.301 a3", 216 "anteater.SEPARATOR.300 ErrNotFound", 217 "anteater.SEPARATOR.000 ErrNotFound", 218 "b_______.SEPARATOR.999 ErrNotFound", 219 "baboon__.SEPARATOR.999 b3", 220 "baboon__.SEPARATOR.302 b3", 221 "baboon__.SEPARATOR.301 ErrNotFound", 222 "baboon__.SEPARATOR.202 ErrNotFound", 223 "baboon__.SEPARATOR.201 b1", 224 "baboon__.SEPARATOR.102 b1", 225 "baboon__.SEPARATOR.101 ErrNotFound", 226 "bear____.SEPARATOR.999 ErrNotFound", 227 "bear____.SEPARATOR.500 b4", 228 "bear____.SEPARATOR.000 ErrNotFound", 229 "buffalo_.SEPARATOR.999 b6", 230 "buffalo_.SEPARATOR.603 b6", 231 "buffalo_.SEPARATOR.602 b6", 232 "buffalo_.SEPARATOR.601 B1", 233 "buffalo_.SEPARATOR.104 B1", 234 "buffalo_.SEPARATOR.103 B1", 235 "buffalo_.SEPARATOR.102 ErrNotFound", 236 "buffalo_.SEPARATOR.000 ErrNotFound", 237 "c_______.SEPARATOR.999 ErrNotFound", 238 "chipmunk.SEPARATOR.999 c2", 239 "chipmunk.SEPARATOR.205 c2", 240 "chipmunk.SEPARATOR.204 c2", 241 "chipmunk.SEPARATOR.203 c1", 242 "chipmunk.SEPARATOR.105 c1", 243 "chipmunk.SEPARATOR.104 c1", 244 "chipmunk.SEPARATOR.103 ErrNotFound", 245 "chipmunk.SEPARATOR.000 ErrNotFound", 246 "d_______.SEPARATOR.999 ErrNotFound", 247 }, 248 }, 249 250 { 251 description: "complex: many tables at many levels", 252 tables: []testTable{ 253 { 254 level: 0, 255 fileNum: 50, 256 data: []string{ 257 "alfalfa__.SET.501 p1", 258 "asparagus.SET.502 p2", 259 "cabbage__.DEL.503 ", 260 "spinach__.MERGE.504 p3", 261 }, 262 }, 263 { 264 level: 0, 265 fileNum: 51, 266 data: []string{ 267 "asparagus.SET.511 q1", 268 "asparagus.SET.512 q2", 269 "asparagus.SET.513 q3", 270 "beans____.SET.514 q4", 271 "broccoli_.SET.515 q5", 272 "cabbage__.SET.516 q6", 273 "celery___.SET.517 q7", 274 "spinach__.MERGE.518 q8", 275 }, 276 }, 277 { 278 level: 1, 279 fileNum: 40, 280 data: []string{ 281 "alfalfa__.SET.410 r1", 282 "asparagus.SET.420 r2", 283 "arugula__.SET.430 r3", 284 }, 285 }, 286 { 287 level: 1, 288 fileNum: 41, 289 data: []string{ 290 "beans____.SET.411 s1", 291 "beans____.SET.421 s2", 292 "bokchoy__.DEL.431 ", 293 "broccoli_.SET.441 s4", 294 }, 295 }, 296 { 297 level: 1, 298 fileNum: 42, 299 data: []string{ 300 "cabbage__.SET.412 t1", 301 "corn_____.DEL.422 ", 302 "spinach__.MERGE.432 t2", 303 }, 304 }, 305 { 306 level: 2, 307 fileNum: 30, 308 data: []string{ 309 "alfalfa__.SET.310 u1", 310 "bokchoy__.SET.320 u2", 311 "celery___.SET.330 u3", 312 "corn_____.SET.340 u4", 313 "spinach__.MERGE.350 u5", 314 }, 315 }, 316 }, 317 queries: []string{ 318 "a________.SEPARATOR.999 ErrNotFound", 319 "alfalfa__.SEPARATOR.520 p1", 320 "alfalfa__.SEPARATOR.510 p1", 321 "alfalfa__.SEPARATOR.500 r1", 322 "alfalfa__.SEPARATOR.400 u1", 323 "alfalfa__.SEPARATOR.300 ErrNotFound", 324 "asparagus.SEPARATOR.520 q3", 325 "asparagus.SEPARATOR.510 p2", 326 "asparagus.SEPARATOR.500 r2", 327 "asparagus.SEPARATOR.400 ErrNotFound", 328 "asparagus.SEPARATOR.300 ErrNotFound", 329 "arugula__.SEPARATOR.520 r3", 330 "arugula__.SEPARATOR.510 r3", 331 "arugula__.SEPARATOR.500 r3", 332 "arugula__.SEPARATOR.400 ErrNotFound", 333 "arugula__.SEPARATOR.300 ErrNotFound", 334 "beans____.SEPARATOR.520 q4", 335 "beans____.SEPARATOR.510 s2", 336 "beans____.SEPARATOR.500 s2", 337 "beans____.SEPARATOR.400 ErrNotFound", 338 "beans____.SEPARATOR.300 ErrNotFound", 339 "bokchoy__.SEPARATOR.520 ErrNotFound", 340 "bokchoy__.SEPARATOR.510 ErrNotFound", 341 "bokchoy__.SEPARATOR.500 ErrNotFound", 342 "bokchoy__.SEPARATOR.400 u2", 343 "bokchoy__.SEPARATOR.300 ErrNotFound", 344 "broccoli_.SEPARATOR.520 q5", 345 "broccoli_.SEPARATOR.510 s4", 346 "broccoli_.SEPARATOR.500 s4", 347 "broccoli_.SEPARATOR.400 ErrNotFound", 348 "broccoli_.SEPARATOR.300 ErrNotFound", 349 "cabbage__.SEPARATOR.520 q6", 350 "cabbage__.SEPARATOR.510 ErrNotFound", 351 "cabbage__.SEPARATOR.500 t1", 352 "cabbage__.SEPARATOR.400 ErrNotFound", 353 "cabbage__.SEPARATOR.300 ErrNotFound", 354 "celery___.SEPARATOR.520 q7", 355 "celery___.SEPARATOR.510 u3", 356 "celery___.SEPARATOR.500 u3", 357 "celery___.SEPARATOR.400 u3", 358 "celery___.SEPARATOR.300 ErrNotFound", 359 "corn_____.SEPARATOR.520 ErrNotFound", 360 "corn_____.SEPARATOR.510 ErrNotFound", 361 "corn_____.SEPARATOR.500 ErrNotFound", 362 "corn_____.SEPARATOR.400 u4", 363 "corn_____.SEPARATOR.300 ErrNotFound", 364 "d________.SEPARATOR.999 ErrNotFound", 365 "spinach__.SEPARATOR.999 u5t2p3q8", 366 "spinach__.SEPARATOR.518 u5t2p3q8", 367 "spinach__.SEPARATOR.517 u5t2p3", 368 "spinach__.SEPARATOR.504 u5t2p3", 369 "spinach__.SEPARATOR.503 u5t2", 370 "spinach__.SEPARATOR.432 u5t2", 371 "spinach__.SEPARATOR.431 u5", 372 "spinach__.SEPARATOR.350 u5", 373 "spinach__.SEPARATOR.349 ErrNotFound", 374 }, 375 }, 376 377 { 378 description: "broken invariants 0: non-increasing level 0 sequence numbers", 379 badOrdering: true, 380 tables: []testTable{ 381 { 382 level: 0, 383 fileNum: 19, 384 data: []string{ 385 "a.SET.101 a", 386 "b.SET.102 b", 387 }, 388 }, 389 { 390 level: 0, 391 fileNum: 20, 392 data: []string{ 393 "c.SET.101 c", 394 }, 395 }, 396 }, 397 }, 398 399 { 400 description: "broken invariants 1: non-increasing level 0 sequence numbers", 401 badOrdering: true, 402 tables: []testTable{ 403 { 404 level: 0, 405 fileNum: 19, 406 data: []string{ 407 "a.SET.101 a", 408 "b.SET.102 b", 409 }, 410 }, 411 { 412 level: 0, 413 fileNum: 20, 414 data: []string{ 415 "c.SET.100 c", 416 "d.SET.101 d", 417 }, 418 }, 419 }, 420 }, 421 422 { 423 description: "broken invariants 2: matching level 0 sequence numbers, considered acceptable", 424 badOrdering: false, 425 tables: []testTable{ 426 { 427 level: 0, 428 fileNum: 19, 429 data: []string{ 430 "a.SET.101 a", 431 }, 432 }, 433 { 434 level: 0, 435 fileNum: 20, 436 data: []string{ 437 "a.SET.101 a", 438 }, 439 }, 440 }, 441 }, 442 443 { 444 description: "broken invariants 3: level non-0 overlapping internal key ranges", 445 badOrdering: true, 446 tables: []testTable{ 447 { 448 level: 5, 449 fileNum: 11, 450 data: []string{ 451 "bat.SET.101 xxx", 452 "dog.SET.102 xxx", 453 }, 454 }, 455 { 456 level: 5, 457 fileNum: 12, 458 data: []string{ 459 "cow.SET.103 xxx", 460 "pig.SET.104 xxx", 461 }, 462 }, 463 }, 464 }, 465 } 466 467 cmp := testkeys.Comparer.Compare 468 equal := testkeys.Comparer.Equal 469 for _, tc := range testCases { 470 desc := tc.description[:strings.Index(tc.description, ":")] 471 472 // m is a map from file numbers to DBs. 473 m := map[FileNum]*memTable{} 474 newIter := func( 475 file *manifest.FileMetadata, _ *IterOptions, _ internalIterOpts, 476 ) (internalIterator, keyspan.FragmentIterator, error) { 477 d, ok := m[file.FileNum] 478 if !ok { 479 return nil, nil, errors.New("no such file") 480 } 481 return d.newIter(nil), nil, nil 482 } 483 484 var files [numLevels][]*fileMetadata 485 for _, tt := range tc.tables { 486 d := newMemTable(memTableOptions{}) 487 m[tt.fileNum] = d 488 489 meta := &fileMetadata{ 490 FileNum: tt.fileNum, 491 } 492 for i, datum := range tt.data { 493 s := strings.Split(datum, " ") 494 ikey := base.ParseInternalKey(s[0]) 495 err := d.set(ikey, []byte(s[1])) 496 if err != nil { 497 t.Fatalf("desc=%q: memtable Set: %v", desc, err) 498 } 499 500 meta.ExtendPointKeyBounds(cmp, ikey, ikey) 501 if i == 0 { 502 meta.SmallestSeqNum = ikey.SeqNum() 503 meta.LargestSeqNum = ikey.SeqNum() 504 } else { 505 if meta.SmallestSeqNum > ikey.SeqNum() { 506 meta.SmallestSeqNum = ikey.SeqNum() 507 } 508 if meta.LargestSeqNum < ikey.SeqNum() { 509 meta.LargestSeqNum = ikey.SeqNum() 510 } 511 } 512 } 513 514 files[tt.level] = append(files[tt.level], meta) 515 } 516 v := manifest.NewVersion(cmp, base.DefaultFormatter, 10<<20, files) 517 err := v.CheckOrdering(cmp, base.DefaultFormatter) 518 if tc.badOrdering && err == nil { 519 t.Errorf("desc=%q: want bad ordering, got nil error", desc) 520 continue 521 } else if !tc.badOrdering && err != nil { 522 t.Errorf("desc=%q: bad ordering: %v", desc, err) 523 continue 524 } 525 526 get := func(v *version, ikey InternalKey) ([]byte, error) { 527 var buf struct { 528 dbi Iterator 529 get getIter 530 } 531 532 get := &buf.get 533 get.cmp = cmp 534 get.equal = equal 535 get.newIters = newIter 536 get.key = ikey.UserKey 537 get.l0 = v.L0SublevelFiles 538 get.version = v 539 get.snapshot = ikey.SeqNum() + 1 540 541 i := &buf.dbi 542 i.comparer = *testkeys.Comparer 543 i.merge = DefaultMerger.Merge 544 i.iter = get 545 546 defer i.Close() 547 if !i.First() { 548 err := i.Error() 549 if err != nil { 550 return nil, err 551 } 552 return nil, ErrNotFound 553 } 554 return i.Value(), nil 555 } 556 557 for _, query := range tc.queries { 558 s := strings.Split(query, " ") 559 ikey := base.ParseInternalKey(s[0]) 560 value, err := get(v, ikey) 561 got, want := "", s[1] 562 if err != nil { 563 if err != ErrNotFound { 564 t.Errorf("desc=%q: query=%q: %v", desc, s[0], err) 565 continue 566 } 567 got = "ErrNotFound" 568 } else { 569 got = string(value) 570 } 571 if got != want { 572 t.Errorf("desc=%q: query=%q: got %q, want %q", desc, s[0], got, want) 573 } 574 } 575 } 576 }