github.com/lbryio/lbcd@v0.22.119/database/internal/treap/treapiter_test.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package treap 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "testing" 11 ) 12 13 // TestMutableIterator ensures that the general behavior of mutable treap 14 // iterators is as expected including tests for first, last, ordered and reverse 15 // ordered iteration, limiting the range, seeking, and initially unpositioned. 16 func TestMutableIterator(t *testing.T) { 17 t.Parallel() 18 19 tests := []struct { 20 numKeys int 21 step int 22 startKey []byte 23 limitKey []byte 24 expectedFirst []byte 25 expectedLast []byte 26 seekKey []byte 27 expectedSeek []byte 28 }{ 29 // No range limits. Values are the set (0, 1, 2, ..., 49). 30 // Seek existing value. 31 { 32 numKeys: 50, 33 step: 1, 34 expectedFirst: serializeUint32(0), 35 expectedLast: serializeUint32(49), 36 seekKey: serializeUint32(12), 37 expectedSeek: serializeUint32(12), 38 }, 39 40 // Limited to range [24, end]. Values are the set 41 // (0, 2, 4, ..., 48). Seek value that doesn't exist and is 42 // greater than largest existing key. 43 { 44 numKeys: 50, 45 step: 2, 46 startKey: serializeUint32(24), 47 expectedFirst: serializeUint32(24), 48 expectedLast: serializeUint32(48), 49 seekKey: serializeUint32(49), 50 expectedSeek: nil, 51 }, 52 53 // Limited to range [start, 25). Values are the set 54 // (0, 3, 6, ..., 48). Seek value that doesn't exist but is 55 // before an existing value within the range. 56 { 57 numKeys: 50, 58 step: 3, 59 limitKey: serializeUint32(25), 60 expectedFirst: serializeUint32(0), 61 expectedLast: serializeUint32(24), 62 seekKey: serializeUint32(17), 63 expectedSeek: serializeUint32(18), 64 }, 65 66 // Limited to range [10, 21). Values are the set 67 // (0, 4, ..., 48). Seek value that exists, but is before the 68 // minimum allowed range. 69 { 70 numKeys: 50, 71 step: 4, 72 startKey: serializeUint32(10), 73 limitKey: serializeUint32(21), 74 expectedFirst: serializeUint32(12), 75 expectedLast: serializeUint32(20), 76 seekKey: serializeUint32(4), 77 expectedSeek: nil, 78 }, 79 80 // Limited by prefix {0,0,0}, range [{0,0,0}, {0,0,1}). 81 // Since it's a bytewise compare, {0,0,0,...} < {0,0,1}. 82 // Seek existing value within the allowed range. 83 { 84 numKeys: 300, 85 step: 1, 86 startKey: []byte{0x00, 0x00, 0x00}, 87 limitKey: []byte{0x00, 0x00, 0x01}, 88 expectedFirst: serializeUint32(0), 89 expectedLast: serializeUint32(255), 90 seekKey: serializeUint32(100), 91 expectedSeek: serializeUint32(100), 92 }, 93 } 94 95 testLoop: 96 for i, test := range tests { 97 // Insert a bunch of keys. 98 testTreap := NewMutable() 99 for i := 0; i < test.numKeys; i += test.step { 100 key := serializeUint32(uint32(i)) 101 testTreap.Put(key, key) 102 } 103 104 // Create new iterator limited by the test params. 105 iter := testTreap.Iterator(test.startKey, test.limitKey) 106 107 // Ensure the first item is accurate. 108 hasFirst := iter.First() 109 if !hasFirst && test.expectedFirst != nil { 110 t.Errorf("First #%d: unexpected exhausted iterator", i) 111 continue 112 } 113 gotKey := iter.Key() 114 if !bytes.Equal(gotKey, test.expectedFirst) { 115 t.Errorf("First.Key #%d: unexpected key - got %x, "+ 116 "want %x", i, gotKey, test.expectedFirst) 117 continue 118 } 119 gotVal := iter.Value() 120 if !bytes.Equal(gotVal, test.expectedFirst) { 121 t.Errorf("First.Value #%d: unexpected value - got %x, "+ 122 "want %x", i, gotVal, test.expectedFirst) 123 continue 124 } 125 126 // Ensure the iterator gives the expected items in order. 127 curNum := binary.BigEndian.Uint32(test.expectedFirst) 128 for iter.Next() { 129 curNum += uint32(test.step) 130 131 // Ensure key is as expected. 132 gotKey := iter.Key() 133 expectedKey := serializeUint32(curNum) 134 if !bytes.Equal(gotKey, expectedKey) { 135 t.Errorf("iter.Key #%d (%d): unexpected key - "+ 136 "got %x, want %x", i, curNum, gotKey, 137 expectedKey) 138 continue testLoop 139 } 140 141 // Ensure value is as expected. 142 gotVal := iter.Value() 143 if !bytes.Equal(gotVal, expectedKey) { 144 t.Errorf("iter.Value #%d (%d): unexpected "+ 145 "value - got %x, want %x", i, curNum, 146 gotVal, expectedKey) 147 continue testLoop 148 } 149 } 150 151 // Ensure iterator is exhausted. 152 if iter.Valid() { 153 t.Errorf("Valid #%d: iterator should be exhausted", i) 154 continue 155 } 156 157 // Ensure the last item is accurate. 158 hasLast := iter.Last() 159 if !hasLast && test.expectedLast != nil { 160 t.Errorf("Last #%d: unexpected exhausted iterator", i) 161 continue 162 } 163 gotKey = iter.Key() 164 if !bytes.Equal(gotKey, test.expectedLast) { 165 t.Errorf("Last.Key #%d: unexpected key - got %x, "+ 166 "want %x", i, gotKey, test.expectedLast) 167 continue 168 } 169 gotVal = iter.Value() 170 if !bytes.Equal(gotVal, test.expectedLast) { 171 t.Errorf("Last.Value #%d: unexpected value - got %x, "+ 172 "want %x", i, gotVal, test.expectedLast) 173 continue 174 } 175 176 // Ensure the iterator gives the expected items in reverse 177 // order. 178 curNum = binary.BigEndian.Uint32(test.expectedLast) 179 for iter.Prev() { 180 curNum -= uint32(test.step) 181 182 // Ensure key is as expected. 183 gotKey := iter.Key() 184 expectedKey := serializeUint32(curNum) 185 if !bytes.Equal(gotKey, expectedKey) { 186 t.Errorf("iter.Key #%d (%d): unexpected key - "+ 187 "got %x, want %x", i, curNum, gotKey, 188 expectedKey) 189 continue testLoop 190 } 191 192 // Ensure value is as expected. 193 gotVal := iter.Value() 194 if !bytes.Equal(gotVal, expectedKey) { 195 t.Errorf("iter.Value #%d (%d): unexpected "+ 196 "value - got %x, want %x", i, curNum, 197 gotVal, expectedKey) 198 continue testLoop 199 } 200 } 201 202 // Ensure iterator is exhausted. 203 if iter.Valid() { 204 t.Errorf("Valid #%d: iterator should be exhausted", i) 205 continue 206 } 207 208 // Seek to the provided key. 209 seekValid := iter.Seek(test.seekKey) 210 if !seekValid && test.expectedSeek != nil { 211 t.Errorf("Seek #%d: unexpected exhausted iterator", i) 212 continue 213 } 214 gotKey = iter.Key() 215 if !bytes.Equal(gotKey, test.expectedSeek) { 216 t.Errorf("Seek.Key #%d: unexpected key - got %x, "+ 217 "want %x", i, gotKey, test.expectedSeek) 218 continue 219 } 220 gotVal = iter.Value() 221 if !bytes.Equal(gotVal, test.expectedSeek) { 222 t.Errorf("Seek.Value #%d: unexpected value - got %x, "+ 223 "want %x", i, gotVal, test.expectedSeek) 224 continue 225 } 226 227 // Recreate the iterator and ensure calling Next on it before it 228 // has been positioned gives the first element. 229 iter = testTreap.Iterator(test.startKey, test.limitKey) 230 hasNext := iter.Next() 231 if !hasNext && test.expectedFirst != nil { 232 t.Errorf("Next #%d: unexpected exhausted iterator", i) 233 continue 234 } 235 gotKey = iter.Key() 236 if !bytes.Equal(gotKey, test.expectedFirst) { 237 t.Errorf("Next.Key #%d: unexpected key - got %x, "+ 238 "want %x", i, gotKey, test.expectedFirst) 239 continue 240 } 241 gotVal = iter.Value() 242 if !bytes.Equal(gotVal, test.expectedFirst) { 243 t.Errorf("Next.Value #%d: unexpected value - got %x, "+ 244 "want %x", i, gotVal, test.expectedFirst) 245 continue 246 } 247 248 // Recreate the iterator and ensure calling Prev on it before it 249 // has been positioned gives the first element. 250 iter = testTreap.Iterator(test.startKey, test.limitKey) 251 hasPrev := iter.Prev() 252 if !hasPrev && test.expectedLast != nil { 253 t.Errorf("Prev #%d: unexpected exhausted iterator", i) 254 continue 255 } 256 gotKey = iter.Key() 257 if !bytes.Equal(gotKey, test.expectedLast) { 258 t.Errorf("Prev.Key #%d: unexpected key - got %x, "+ 259 "want %x", i, gotKey, test.expectedLast) 260 continue 261 } 262 gotVal = iter.Value() 263 if !bytes.Equal(gotVal, test.expectedLast) { 264 t.Errorf("Next.Value #%d: unexpected value - got %x, "+ 265 "want %x", i, gotVal, test.expectedLast) 266 continue 267 } 268 } 269 } 270 271 // TestMutableEmptyIterator ensures that the various functions behave as 272 // expected when a mutable treap is empty. 273 func TestMutableEmptyIterator(t *testing.T) { 274 t.Parallel() 275 276 // Create iterator against empty treap. 277 testTreap := NewMutable() 278 iter := testTreap.Iterator(nil, nil) 279 280 // Ensure Valid on empty iterator reports it as exhausted. 281 if iter.Valid() { 282 t.Fatal("Valid: iterator should be exhausted") 283 } 284 285 // Ensure First and Last on empty iterator report it as exhausted. 286 if iter.First() { 287 t.Fatal("First: iterator should be exhausted") 288 } 289 if iter.Last() { 290 t.Fatal("Last: iterator should be exhausted") 291 } 292 293 // Ensure Next and Prev on empty iterator report it as exhausted. 294 if iter.Next() { 295 t.Fatal("Next: iterator should be exhausted") 296 } 297 if iter.Prev() { 298 t.Fatal("Prev: iterator should be exhausted") 299 } 300 301 // Ensure Key and Value on empty iterator are nil. 302 if gotKey := iter.Key(); gotKey != nil { 303 t.Fatalf("Key: should be nil - got %q", gotKey) 304 } 305 if gotVal := iter.Value(); gotVal != nil { 306 t.Fatalf("Value: should be nil - got %q", gotVal) 307 } 308 309 // Ensure Next and Prev report exhausted after forcing a reseek on an 310 // empty iterator. 311 iter.ForceReseek() 312 if iter.Next() { 313 t.Fatal("Next: iterator should be exhausted") 314 } 315 iter.ForceReseek() 316 if iter.Prev() { 317 t.Fatal("Prev: iterator should be exhausted") 318 } 319 } 320 321 // TestIteratorUpdates ensures that issuing a call to ForceReseek on an iterator 322 // that had the underlying mutable treap updated works as expected. 323 func TestIteratorUpdates(t *testing.T) { 324 t.Parallel() 325 326 // Create a new treap with various values inserted in no particular 327 // order. The resulting keys are the set (2, 4, 7, 11, 18, 25). 328 testTreap := NewMutable() 329 testTreap.Put(serializeUint32(7), nil) 330 testTreap.Put(serializeUint32(2), nil) 331 testTreap.Put(serializeUint32(18), nil) 332 testTreap.Put(serializeUint32(11), nil) 333 testTreap.Put(serializeUint32(25), nil) 334 testTreap.Put(serializeUint32(4), nil) 335 336 // Create an iterator against the treap with a range that excludes the 337 // lowest and highest entries. The limited set is then (4, 7, 11, 18) 338 iter := testTreap.Iterator(serializeUint32(3), serializeUint32(25)) 339 340 // Delete a key from the middle of the range and notify the iterator to 341 // force a reseek. 342 testTreap.Delete(serializeUint32(11)) 343 iter.ForceReseek() 344 345 // Ensure that calling Next on the iterator after the forced reseek 346 // gives the expected key. The limited set of keys at this point is 347 // (4, 7, 18) and the iterator has not yet been positioned. 348 if !iter.Next() { 349 t.Fatal("ForceReseek.Next: unexpected exhausted iterator") 350 } 351 wantKey := serializeUint32(4) 352 gotKey := iter.Key() 353 if !bytes.Equal(gotKey, wantKey) { 354 t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x", 355 gotKey, wantKey) 356 } 357 358 // Delete the key the iterator is currently position at and notify the 359 // iterator to force a reseek. 360 testTreap.Delete(serializeUint32(4)) 361 iter.ForceReseek() 362 363 // Ensure that calling Next on the iterator after the forced reseek 364 // gives the expected key. The limited set of keys at this point is 365 // (7, 18) and the iterator is positioned at a deleted entry before 7. 366 if !iter.Next() { 367 t.Fatal("ForceReseek.Next: unexpected exhausted iterator") 368 } 369 wantKey = serializeUint32(7) 370 gotKey = iter.Key() 371 if !bytes.Equal(gotKey, wantKey) { 372 t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x", 373 gotKey, wantKey) 374 } 375 376 // Add a key before the current key the iterator is position at and 377 // notify the iterator to force a reseek. 378 testTreap.Put(serializeUint32(4), nil) 379 iter.ForceReseek() 380 381 // Ensure that calling Prev on the iterator after the forced reseek 382 // gives the expected key. The limited set of keys at this point is 383 // (4, 7, 18) and the iterator is positioned at 7. 384 if !iter.Prev() { 385 t.Fatal("ForceReseek.Prev: unexpected exhausted iterator") 386 } 387 wantKey = serializeUint32(4) 388 gotKey = iter.Key() 389 if !bytes.Equal(gotKey, wantKey) { 390 t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x", 391 gotKey, wantKey) 392 } 393 394 // Delete the next key the iterator would ordinarily move to then notify 395 // the iterator to force a reseek. 396 testTreap.Delete(serializeUint32(7)) 397 iter.ForceReseek() 398 399 // Ensure that calling Next on the iterator after the forced reseek 400 // gives the expected key. The limited set of keys at this point is 401 // (4, 18) and the iterator is positioned at 4. 402 if !iter.Next() { 403 t.Fatal("ForceReseek.Next: unexpected exhausted iterator") 404 } 405 wantKey = serializeUint32(18) 406 gotKey = iter.Key() 407 if !bytes.Equal(gotKey, wantKey) { 408 t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x", 409 gotKey, wantKey) 410 } 411 } 412 413 // TestImmutableIterator ensures that the general behavior of immutable treap 414 // iterators is as expected including tests for first, last, ordered and reverse 415 // ordered iteration, limiting the range, seeking, and initially unpositioned. 416 func TestImmutableIterator(t *testing.T) { 417 t.Parallel() 418 419 tests := []struct { 420 numKeys int 421 step int 422 startKey []byte 423 limitKey []byte 424 expectedFirst []byte 425 expectedLast []byte 426 seekKey []byte 427 expectedSeek []byte 428 }{ 429 // No range limits. Values are the set (0, 1, 2, ..., 49). 430 // Seek existing value. 431 { 432 numKeys: 50, 433 step: 1, 434 expectedFirst: serializeUint32(0), 435 expectedLast: serializeUint32(49), 436 seekKey: serializeUint32(12), 437 expectedSeek: serializeUint32(12), 438 }, 439 440 // Limited to range [24, end]. Values are the set 441 // (0, 2, 4, ..., 48). Seek value that doesn't exist and is 442 // greater than largest existing key. 443 { 444 numKeys: 50, 445 step: 2, 446 startKey: serializeUint32(24), 447 expectedFirst: serializeUint32(24), 448 expectedLast: serializeUint32(48), 449 seekKey: serializeUint32(49), 450 expectedSeek: nil, 451 }, 452 453 // Limited to range [start, 25). Values are the set 454 // (0, 3, 6, ..., 48). Seek value that doesn't exist but is 455 // before an existing value within the range. 456 { 457 numKeys: 50, 458 step: 3, 459 limitKey: serializeUint32(25), 460 expectedFirst: serializeUint32(0), 461 expectedLast: serializeUint32(24), 462 seekKey: serializeUint32(17), 463 expectedSeek: serializeUint32(18), 464 }, 465 466 // Limited to range [10, 21). Values are the set 467 // (0, 4, ..., 48). Seek value that exists, but is before the 468 // minimum allowed range. 469 { 470 numKeys: 50, 471 step: 4, 472 startKey: serializeUint32(10), 473 limitKey: serializeUint32(21), 474 expectedFirst: serializeUint32(12), 475 expectedLast: serializeUint32(20), 476 seekKey: serializeUint32(4), 477 expectedSeek: nil, 478 }, 479 480 // Limited by prefix {0,0,0}, range [{0,0,0}, {0,0,1}). 481 // Since it's a bytewise compare, {0,0,0,...} < {0,0,1}. 482 // Seek existing value within the allowed range. 483 { 484 numKeys: 300, 485 step: 1, 486 startKey: []byte{0x00, 0x00, 0x00}, 487 limitKey: []byte{0x00, 0x00, 0x01}, 488 expectedFirst: serializeUint32(0), 489 expectedLast: serializeUint32(255), 490 seekKey: serializeUint32(100), 491 expectedSeek: serializeUint32(100), 492 }, 493 } 494 495 testLoop: 496 for i, test := range tests { 497 // Insert a bunch of keys. 498 testTreap := NewImmutable() 499 for i := 0; i < test.numKeys; i += test.step { 500 key := serializeUint32(uint32(i)) 501 testTreap = testTreap.Put(key, key) 502 } 503 504 // Create new iterator limited by the test params. 505 iter := testTreap.Iterator(test.startKey, test.limitKey) 506 507 // Ensure the first item is accurate. 508 hasFirst := iter.First() 509 if !hasFirst && test.expectedFirst != nil { 510 t.Errorf("First #%d: unexpected exhausted iterator", i) 511 continue 512 } 513 gotKey := iter.Key() 514 if !bytes.Equal(gotKey, test.expectedFirst) { 515 t.Errorf("First.Key #%d: unexpected key - got %x, "+ 516 "want %x", i, gotKey, test.expectedFirst) 517 continue 518 } 519 gotVal := iter.Value() 520 if !bytes.Equal(gotVal, test.expectedFirst) { 521 t.Errorf("First.Value #%d: unexpected value - got %x, "+ 522 "want %x", i, gotVal, test.expectedFirst) 523 continue 524 } 525 526 // Ensure the iterator gives the expected items in order. 527 curNum := binary.BigEndian.Uint32(test.expectedFirst) 528 for iter.Next() { 529 curNum += uint32(test.step) 530 531 // Ensure key is as expected. 532 gotKey := iter.Key() 533 expectedKey := serializeUint32(curNum) 534 if !bytes.Equal(gotKey, expectedKey) { 535 t.Errorf("iter.Key #%d (%d): unexpected key - "+ 536 "got %x, want %x", i, curNum, gotKey, 537 expectedKey) 538 continue testLoop 539 } 540 541 // Ensure value is as expected. 542 gotVal := iter.Value() 543 if !bytes.Equal(gotVal, expectedKey) { 544 t.Errorf("iter.Value #%d (%d): unexpected "+ 545 "value - got %x, want %x", i, curNum, 546 gotVal, expectedKey) 547 continue testLoop 548 } 549 } 550 551 // Ensure iterator is exhausted. 552 if iter.Valid() { 553 t.Errorf("Valid #%d: iterator should be exhausted", i) 554 continue 555 } 556 557 // Ensure the last item is accurate. 558 hasLast := iter.Last() 559 if !hasLast && test.expectedLast != nil { 560 t.Errorf("Last #%d: unexpected exhausted iterator", i) 561 continue 562 } 563 gotKey = iter.Key() 564 if !bytes.Equal(gotKey, test.expectedLast) { 565 t.Errorf("Last.Key #%d: unexpected key - got %x, "+ 566 "want %x", i, gotKey, test.expectedLast) 567 continue 568 } 569 gotVal = iter.Value() 570 if !bytes.Equal(gotVal, test.expectedLast) { 571 t.Errorf("Last.Value #%d: unexpected value - got %x, "+ 572 "want %x", i, gotVal, test.expectedLast) 573 continue 574 } 575 576 // Ensure the iterator gives the expected items in reverse 577 // order. 578 curNum = binary.BigEndian.Uint32(test.expectedLast) 579 for iter.Prev() { 580 curNum -= uint32(test.step) 581 582 // Ensure key is as expected. 583 gotKey := iter.Key() 584 expectedKey := serializeUint32(curNum) 585 if !bytes.Equal(gotKey, expectedKey) { 586 t.Errorf("iter.Key #%d (%d): unexpected key - "+ 587 "got %x, want %x", i, curNum, gotKey, 588 expectedKey) 589 continue testLoop 590 } 591 592 // Ensure value is as expected. 593 gotVal := iter.Value() 594 if !bytes.Equal(gotVal, expectedKey) { 595 t.Errorf("iter.Value #%d (%d): unexpected "+ 596 "value - got %x, want %x", i, curNum, 597 gotVal, expectedKey) 598 continue testLoop 599 } 600 } 601 602 // Ensure iterator is exhausted. 603 if iter.Valid() { 604 t.Errorf("Valid #%d: iterator should be exhausted", i) 605 continue 606 } 607 608 // Seek to the provided key. 609 seekValid := iter.Seek(test.seekKey) 610 if !seekValid && test.expectedSeek != nil { 611 t.Errorf("Seek #%d: unexpected exhausted iterator", i) 612 continue 613 } 614 gotKey = iter.Key() 615 if !bytes.Equal(gotKey, test.expectedSeek) { 616 t.Errorf("Seek.Key #%d: unexpected key - got %x, "+ 617 "want %x", i, gotKey, test.expectedSeek) 618 continue 619 } 620 gotVal = iter.Value() 621 if !bytes.Equal(gotVal, test.expectedSeek) { 622 t.Errorf("Seek.Value #%d: unexpected value - got %x, "+ 623 "want %x", i, gotVal, test.expectedSeek) 624 continue 625 } 626 627 // Recreate the iterator and ensure calling Next on it before it 628 // has been positioned gives the first element. 629 iter = testTreap.Iterator(test.startKey, test.limitKey) 630 hasNext := iter.Next() 631 if !hasNext && test.expectedFirst != nil { 632 t.Errorf("Next #%d: unexpected exhausted iterator", i) 633 continue 634 } 635 gotKey = iter.Key() 636 if !bytes.Equal(gotKey, test.expectedFirst) { 637 t.Errorf("Next.Key #%d: unexpected key - got %x, "+ 638 "want %x", i, gotKey, test.expectedFirst) 639 continue 640 } 641 gotVal = iter.Value() 642 if !bytes.Equal(gotVal, test.expectedFirst) { 643 t.Errorf("Next.Value #%d: unexpected value - got %x, "+ 644 "want %x", i, gotVal, test.expectedFirst) 645 continue 646 } 647 648 // Recreate the iterator and ensure calling Prev on it before it 649 // has been positioned gives the first element. 650 iter = testTreap.Iterator(test.startKey, test.limitKey) 651 hasPrev := iter.Prev() 652 if !hasPrev && test.expectedLast != nil { 653 t.Errorf("Prev #%d: unexpected exhausted iterator", i) 654 continue 655 } 656 gotKey = iter.Key() 657 if !bytes.Equal(gotKey, test.expectedLast) { 658 t.Errorf("Prev.Key #%d: unexpected key - got %x, "+ 659 "want %x", i, gotKey, test.expectedLast) 660 continue 661 } 662 gotVal = iter.Value() 663 if !bytes.Equal(gotVal, test.expectedLast) { 664 t.Errorf("Next.Value #%d: unexpected value - got %x, "+ 665 "want %x", i, gotVal, test.expectedLast) 666 continue 667 } 668 } 669 } 670 671 // TestImmutableEmptyIterator ensures that the various functions behave as 672 // expected when an immutable treap is empty. 673 func TestImmutableEmptyIterator(t *testing.T) { 674 t.Parallel() 675 676 // Create iterator against empty treap. 677 testTreap := NewImmutable() 678 iter := testTreap.Iterator(nil, nil) 679 680 // Ensure Valid on empty iterator reports it as exhausted. 681 if iter.Valid() { 682 t.Fatal("Valid: iterator should be exhausted") 683 } 684 685 // Ensure First and Last on empty iterator report it as exhausted. 686 if iter.First() { 687 t.Fatal("First: iterator should be exhausted") 688 } 689 if iter.Last() { 690 t.Fatal("Last: iterator should be exhausted") 691 } 692 693 // Ensure Next and Prev on empty iterator report it as exhausted. 694 if iter.Next() { 695 t.Fatal("Next: iterator should be exhausted") 696 } 697 if iter.Prev() { 698 t.Fatal("Prev: iterator should be exhausted") 699 } 700 701 // Ensure Key and Value on empty iterator are nil. 702 if gotKey := iter.Key(); gotKey != nil { 703 t.Fatalf("Key: should be nil - got %q", gotKey) 704 } 705 if gotVal := iter.Value(); gotVal != nil { 706 t.Fatalf("Value: should be nil - got %q", gotVal) 707 } 708 709 // Ensure calling ForceReseek on an immutable treap iterator does not 710 // cause any issues since it only applies to mutable treap iterators. 711 iter.ForceReseek() 712 if iter.Next() { 713 t.Fatal("Next: iterator should be exhausted") 714 } 715 iter.ForceReseek() 716 if iter.Prev() { 717 t.Fatal("Prev: iterator should be exhausted") 718 } 719 }