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