1 // Copyright (c) 2017 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <algorithm> 16 #include <iostream> 17 #include <set> 18 #include <string> 19 #include <vector> 20 21 #include "gmock/gmock.h" 22 #include "source/comp/move_to_front.h" 23 24 namespace spvtools { 25 namespace comp { 26 namespace { 27 28 // Class used to test the inner workings of MoveToFront. 29 class MoveToFrontTester : public MoveToFront { 30 public: 31 // Inserts the value in the internal tree data structure. For testing only. 32 void TestInsert(uint32_t val) { InsertNode(CreateNode(val, val)); } 33 34 // Removes the value from the internal tree data structure. For testing only. 35 void TestRemove(uint32_t val) { 36 const auto it = value_to_node_.find(val); 37 assert(it != value_to_node_.end()); 38 RemoveNode(it->second); 39 } 40 41 // Prints the internal tree data structure to |out|. For testing only. 42 void PrintTree(std::ostream& out, bool print_timestamp = false) const { 43 if (root_) PrintTreeInternal(out, root_, 1, print_timestamp); 44 } 45 46 // Returns node handle corresponding to the value. The value may not be in the 47 // tree. 48 uint32_t GetNodeHandle(uint32_t value) const { 49 const auto it = value_to_node_.find(value); 50 if (it == value_to_node_.end()) return 0; 51 52 return it->second; 53 } 54 55 // Returns total node count (both those in the tree and removed, 56 // but not the NIL singleton). 57 size_t GetTotalNodeCount() const { 58 assert(nodes_.size()); 59 return nodes_.size() - 1; 60 } 61 62 uint32_t GetLastAccessedValue() const { return last_accessed_value_; } 63 64 private: 65 // Prints the internal tree data structure for debug purposes in the following 66 // format: 67 // 10H3S4----5H1S1-----D2 68 // 15H2S2----12H1S1----D3 69 // Right links are horizontal, left links step down one line. 70 // 5H1S1 is read as value 5, height 1, size 1. Optionally node label can also 71 // contain timestamp (5H1S1T15). D3 stands for depth 3. 72 void PrintTreeInternal(std::ostream& out, uint32_t node, size_t depth, 73 bool print_timestamp) const; 74 }; 75 76 void MoveToFrontTester::PrintTreeInternal(std::ostream& out, uint32_t node, 77 size_t depth, 78 bool print_timestamp) const { 79 if (!node) { 80 out << "D" << depth - 1 << std::endl; 81 return; 82 } 83 84 const size_t kTextFieldWvaluethWithoutTimestamp = 10; 85 const size_t kTextFieldWvaluethWithTimestamp = 14; 86 const size_t text_field_wvalueth = print_timestamp 87 ? kTextFieldWvaluethWithTimestamp 88 : kTextFieldWvaluethWithoutTimestamp; 89 90 std::stringstream label; 91 label << ValueOf(node) << "H" << HeightOf(node) << "S" << SizeOf(node); 92 if (print_timestamp) label << "T" << TimestampOf(node); 93 const size_t label_length = label.str().length(); 94 if (label_length < text_field_wvalueth) 95 label << std::string(text_field_wvalueth - label_length, '-'); 96 97 out << label.str(); 98 99 PrintTreeInternal(out, RightOf(node), depth + 1, print_timestamp); 100 101 if (LeftOf(node)) { 102 out << std::string(depth * text_field_wvalueth, ' '); 103 PrintTreeInternal(out, LeftOf(node), depth + 1, print_timestamp); 104 } 105 } 106 107 void CheckTree(const MoveToFrontTester& mtf, const std::string& expected, 108 bool print_timestamp = false) { 109 std::stringstream ss; 110 mtf.PrintTree(ss, print_timestamp); 111 EXPECT_EQ(expected, ss.str()); 112 } 113 114 TEST(MoveToFront, EmptyTree) { 115 MoveToFrontTester mtf; 116 CheckTree(mtf, std::string()); 117 } 118 119 TEST(MoveToFront, InsertLeftRotation) { 120 MoveToFrontTester mtf; 121 122 mtf.TestInsert(30); 123 mtf.TestInsert(20); 124 125 CheckTree(mtf, std::string(R"( 126 30H2S2----20H1S1----D2 127 )") 128 .substr(1)); 129 130 mtf.TestInsert(10); 131 CheckTree(mtf, std::string(R"( 132 20H2S3----10H1S1----D2 133 30H1S1----D2 134 )") 135 .substr(1)); 136 } 137 138 TEST(MoveToFront, InsertRightRotation) { 139 MoveToFrontTester mtf; 140 141 mtf.TestInsert(10); 142 mtf.TestInsert(20); 143 144 CheckTree(mtf, std::string(R"( 145 10H2S2----D1 146 20H1S1----D2 147 )") 148 .substr(1)); 149 150 mtf.TestInsert(30); 151 CheckTree(mtf, std::string(R"( 152 20H2S3----10H1S1----D2 153 30H1S1----D2 154 )") 155 .substr(1)); 156 } 157 158 TEST(MoveToFront, InsertRightLeftRotation) { 159 MoveToFrontTester mtf; 160 161 mtf.TestInsert(30); 162 mtf.TestInsert(20); 163 164 CheckTree(mtf, std::string(R"( 165 30H2S2----20H1S1----D2 166 )") 167 .substr(1)); 168 169 mtf.TestInsert(25); 170 CheckTree(mtf, std::string(R"( 171 25H2S3----20H1S1----D2 172 30H1S1----D2 173 )") 174 .substr(1)); 175 } 176 177 TEST(MoveToFront, InsertLeftRightRotation) { 178 MoveToFrontTester mtf; 179 180 mtf.TestInsert(10); 181 mtf.TestInsert(20); 182 183 CheckTree(mtf, std::string(R"( 184 10H2S2----D1 185 20H1S1----D2 186 )") 187 .substr(1)); 188 189 mtf.TestInsert(15); 190 CheckTree(mtf, std::string(R"( 191 15H2S3----10H1S1----D2 192 20H1S1----D2 193 )") 194 .substr(1)); 195 } 196 197 TEST(MoveToFront, RemoveSingleton) { 198 MoveToFrontTester mtf; 199 200 mtf.TestInsert(10); 201 CheckTree(mtf, std::string(R"( 202 10H1S1----D1 203 )") 204 .substr(1)); 205 206 mtf.TestRemove(10); 207 CheckTree(mtf, ""); 208 } 209 210 TEST(MoveToFront, RemoveRootWithScapegoat) { 211 MoveToFrontTester mtf; 212 213 mtf.TestInsert(10); 214 mtf.TestInsert(5); 215 mtf.TestInsert(15); 216 CheckTree(mtf, std::string(R"( 217 10H2S3----5H1S1-----D2 218 15H1S1----D2 219 )") 220 .substr(1)); 221 222 mtf.TestRemove(10); 223 CheckTree(mtf, std::string(R"( 224 15H2S2----5H1S1-----D2 225 )") 226 .substr(1)); 227 } 228 229 TEST(MoveToFront, RemoveRightRotation) { 230 MoveToFrontTester mtf; 231 232 mtf.TestInsert(10); 233 mtf.TestInsert(5); 234 mtf.TestInsert(15); 235 mtf.TestInsert(20); 236 CheckTree(mtf, std::string(R"( 237 10H3S4----5H1S1-----D2 238 15H2S2----D2 239 20H1S1----D3 240 )") 241 .substr(1)); 242 243 mtf.TestRemove(5); 244 245 CheckTree(mtf, std::string(R"( 246 15H2S3----10H1S1----D2 247 20H1S1----D2 248 )") 249 .substr(1)); 250 } 251 252 TEST(MoveToFront, RemoveLeftRotation) { 253 MoveToFrontTester mtf; 254 255 mtf.TestInsert(10); 256 mtf.TestInsert(15); 257 mtf.TestInsert(5); 258 mtf.TestInsert(1); 259 CheckTree(mtf, std::string(R"( 260 10H3S4----5H2S2-----1H1S1-----D3 261 15H1S1----D2 262 )") 263 .substr(1)); 264 265 mtf.TestRemove(15); 266 267 CheckTree(mtf, std::string(R"( 268 5H2S3-----1H1S1-----D2 269 10H1S1----D2 270 )") 271 .substr(1)); 272 } 273 274 TEST(MoveToFront, RemoveLeftRightRotation) { 275 MoveToFrontTester mtf; 276 277 mtf.TestInsert(10); 278 mtf.TestInsert(15); 279 mtf.TestInsert(5); 280 mtf.TestInsert(12); 281 CheckTree(mtf, std::string(R"( 282 10H3S4----5H1S1-----D2 283 15H2S2----12H1S1----D3 284 )") 285 .substr(1)); 286 287 mtf.TestRemove(5); 288 289 CheckTree(mtf, std::string(R"( 290 12H2S3----10H1S1----D2 291 15H1S1----D2 292 )") 293 .substr(1)); 294 } 295 296 TEST(MoveToFront, RemoveRightLeftRotation) { 297 MoveToFrontTester mtf; 298 299 mtf.TestInsert(10); 300 mtf.TestInsert(15); 301 mtf.TestInsert(5); 302 mtf.TestInsert(8); 303 CheckTree(mtf, std::string(R"( 304 10H3S4----5H2S2-----D2 305 8H1S1-----D3 306 15H1S1----D2 307 )") 308 .substr(1)); 309 310 mtf.TestRemove(15); 311 312 CheckTree(mtf, std::string(R"( 313 8H2S3-----5H1S1-----D2 314 10H1S1----D2 315 )") 316 .substr(1)); 317 } 318 319 TEST(MoveToFront, MultipleOperations) { 320 MoveToFrontTester mtf; 321 std::vector<uint32_t> vals = {5, 11, 12, 16, 15, 6, 14, 2, 322 7, 10, 4, 8, 9, 3, 1, 13}; 323 324 for (uint32_t i : vals) { 325 mtf.TestInsert(i); 326 } 327 328 CheckTree(mtf, std::string(R"( 329 11H5S16---5H4S10----3H3S4-----2H2S2-----1H1S1-----D5 330 4H1S1-----D4 331 7H3S5-----6H1S1-----D4 332 9H2S3-----8H1S1-----D5 333 10H1S1----D5 334 15H3S5----13H2S3----12H1S1----D4 335 14H1S1----D4 336 16H1S1----D3 337 )") 338 .substr(1)); 339 340 mtf.TestRemove(11); 341 342 CheckTree(mtf, std::string(R"( 343 10H5S15---5H4S9-----3H3S4-----2H2S2-----1H1S1-----D5 344 4H1S1-----D4 345 7H3S4-----6H1S1-----D4 346 9H2S2-----8H1S1-----D5 347 15H3S5----13H2S3----12H1S1----D4 348 14H1S1----D4 349 16H1S1----D3 350 )") 351 .substr(1)); 352 353 mtf.TestInsert(11); 354 355 CheckTree(mtf, std::string(R"( 356 10H5S16---5H4S9-----3H3S4-----2H2S2-----1H1S1-----D5 357 4H1S1-----D4 358 7H3S4-----6H1S1-----D4 359 9H2S2-----8H1S1-----D5 360 13H3S6----12H2S2----11H1S1----D4 361 15H2S3----14H1S1----D4 362 16H1S1----D4 363 )") 364 .substr(1)); 365 366 mtf.TestRemove(5); 367 368 CheckTree(mtf, std::string(R"( 369 10H5S15---6H4S8-----3H3S4-----2H2S2-----1H1S1-----D5 370 4H1S1-----D4 371 8H2S3-----7H1S1-----D4 372 9H1S1-----D4 373 13H3S6----12H2S2----11H1S1----D4 374 15H2S3----14H1S1----D4 375 16H1S1----D4 376 )") 377 .substr(1)); 378 379 mtf.TestInsert(5); 380 381 CheckTree(mtf, std::string(R"( 382 10H5S16---6H4S9-----3H3S5-----2H2S2-----1H1S1-----D5 383 4H2S2-----D4 384 5H1S1-----D5 385 8H2S3-----7H1S1-----D4 386 9H1S1-----D4 387 13H3S6----12H2S2----11H1S1----D4 388 15H2S3----14H1S1----D4 389 16H1S1----D4 390 )") 391 .substr(1)); 392 393 mtf.TestRemove(2); 394 mtf.TestRemove(1); 395 mtf.TestRemove(4); 396 mtf.TestRemove(3); 397 mtf.TestRemove(6); 398 mtf.TestRemove(5); 399 mtf.TestRemove(7); 400 mtf.TestRemove(9); 401 402 CheckTree(mtf, std::string(R"( 403 13H4S8----10H3S4----8H1S1-----D3 404 12H2S2----11H1S1----D4 405 15H2S3----14H1S1----D3 406 16H1S1----D3 407 )") 408 .substr(1)); 409 } 410 411 TEST(MoveToFront, BiggerScaleTreeTest) { 412 MoveToFrontTester mtf; 413 std::set<uint32_t> all_vals; 414 415 const uint32_t kMagic1 = 2654435761; 416 const uint32_t kMagic2 = 10000; 417 418 for (uint32_t i = 1; i < 1000; ++i) { 419 const uint32_t val = (i * kMagic1) % kMagic2; 420 if (!all_vals.count(val)) { 421 mtf.TestInsert(val); 422 all_vals.insert(val); 423 } 424 } 425 426 for (uint32_t i = 1; i < 1000; ++i) { 427 const uint32_t val = (i * kMagic1) % kMagic2; 428 if (val % 2 == 0) { 429 mtf.TestRemove(val); 430 all_vals.erase(val); 431 } 432 } 433 434 for (uint32_t i = 1000; i < 2000; ++i) { 435 const uint32_t val = (i * kMagic1) % kMagic2; 436 if (!all_vals.count(val)) { 437 mtf.TestInsert(val); 438 all_vals.insert(val); 439 } 440 } 441 442 for (uint32_t i = 1; i < 2000; ++i) { 443 const uint32_t val = (i * kMagic1) % kMagic2; 444 if (val > 50) { 445 mtf.TestRemove(val); 446 all_vals.erase(val); 447 } 448 } 449 450 EXPECT_EQ(all_vals, std::set<uint32_t>({2, 4, 11, 13, 24, 33, 35, 37, 46})); 451 452 CheckTree(mtf, std::string(R"( 453 33H4S9----11H3S5----2H2S2-----D3 454 4H1S1-----D4 455 13H2S2----D3 456 24H1S1----D4 457 37H2S3----35H1S1----D3 458 46H1S1----D3 459 )") 460 .substr(1)); 461 } 462 463 TEST(MoveToFront, RankFromValue) { 464 MoveToFrontTester mtf; 465 466 uint32_t rank = 0; 467 EXPECT_FALSE(mtf.RankFromValue(1, &rank)); 468 469 EXPECT_TRUE(mtf.Insert(1)); 470 EXPECT_TRUE(mtf.Insert(2)); 471 EXPECT_TRUE(mtf.Insert(3)); 472 EXPECT_FALSE(mtf.Insert(2)); 473 CheckTree(mtf, 474 std::string(R"( 475 2H2S3T2-------1H1S1T1-------D2 476 3H1S1T3-------D2 477 )") 478 .substr(1), 479 /* print_timestamp = */ true); 480 481 EXPECT_FALSE(mtf.RankFromValue(4, &rank)); 482 483 EXPECT_TRUE(mtf.RankFromValue(1, &rank)); 484 EXPECT_EQ(3u, rank); 485 486 CheckTree(mtf, 487 std::string(R"( 488 3H2S3T3-------2H1S1T2-------D2 489 1H1S1T4-------D2 490 )") 491 .substr(1), 492 /* print_timestamp = */ true); 493 494 EXPECT_TRUE(mtf.RankFromValue(1, &rank)); 495 EXPECT_EQ(1u, rank); 496 497 EXPECT_TRUE(mtf.RankFromValue(3, &rank)); 498 EXPECT_EQ(2u, rank); 499 500 EXPECT_TRUE(mtf.RankFromValue(2, &rank)); 501 EXPECT_EQ(3u, rank); 502 503 EXPECT_TRUE(mtf.Insert(40)); 504 505 EXPECT_TRUE(mtf.RankFromValue(1, &rank)); 506 EXPECT_EQ(4u, rank); 507 508 EXPECT_TRUE(mtf.Insert(50)); 509 510 EXPECT_TRUE(mtf.RankFromValue(1, &rank)); 511 EXPECT_EQ(2u, rank); 512 513 CheckTree(mtf, 514 std::string(R"( 515 2H3S5T6-------3H1S1T5-------D2 516 50H2S3T9------40H1S1T7------D3 517 1H1S1T10------D3 518 )") 519 .substr(1), 520 /* print_timestamp = */ true); 521 522 EXPECT_TRUE(mtf.RankFromValue(50, &rank)); 523 EXPECT_EQ(2u, rank); 524 525 EXPECT_EQ(5u, mtf.GetSize()); 526 CheckTree(mtf, 527 std::string(R"( 528 2H3S5T6-------3H1S1T5-------D2 529 1H2S3T10------40H1S1T7------D3 530 50H1S1T11-----D3 531 )") 532 .substr(1), 533 /* print_timestamp = */ true); 534 535 EXPECT_FALSE(mtf.RankFromValue(0, &rank)); 536 EXPECT_FALSE(mtf.RankFromValue(20, &rank)); 537 } 538 539 TEST(MoveToFront, ValueFromRank) { 540 MoveToFrontTester mtf; 541 542 uint32_t value = 0; 543 EXPECT_FALSE(mtf.ValueFromRank(0, &value)); 544 EXPECT_FALSE(mtf.ValueFromRank(1, &value)); 545 546 EXPECT_TRUE(mtf.Insert(1)); 547 EXPECT_EQ(1u, mtf.GetLastAccessedValue()); 548 EXPECT_TRUE(mtf.Insert(2)); 549 EXPECT_EQ(2u, mtf.GetLastAccessedValue()); 550 EXPECT_TRUE(mtf.Insert(3)); 551 EXPECT_EQ(3u, mtf.GetLastAccessedValue()); 552 553 EXPECT_TRUE(mtf.ValueFromRank(3, &value)); 554 EXPECT_EQ(1u, value); 555 EXPECT_EQ(1u, mtf.GetLastAccessedValue()); 556 557 EXPECT_TRUE(mtf.ValueFromRank(1, &value)); 558 EXPECT_EQ(1u, value); 559 EXPECT_EQ(1u, mtf.GetLastAccessedValue()); 560 561 CheckTree(mtf, 562 std::string(R"( 563 3H2S3T3-------2H1S1T2-------D2 564 1H1S1T4-------D2 565 )") 566 .substr(1), 567 /* print_timestamp = */ true); 568 569 EXPECT_TRUE(mtf.ValueFromRank(2, &value)); 570 EXPECT_EQ(3u, value); 571 572 EXPECT_EQ(3u, mtf.GetSize()); 573 574 CheckTree(mtf, 575 std::string(R"( 576 1H2S3T4-------2H1S1T2-------D2 577 3H1S1T5-------D2 578 )") 579 .substr(1), 580 /* print_timestamp = */ true); 581 582 EXPECT_TRUE(mtf.ValueFromRank(3, &value)); 583 EXPECT_EQ(2u, value); 584 585 CheckTree(mtf, 586 std::string(R"( 587 3H2S3T5-------1H1S1T4-------D2 588 2H1S1T6-------D2 589 )") 590 .substr(1), 591 /* print_timestamp = */ true); 592 593 EXPECT_TRUE(mtf.Insert(10)); 594 CheckTree(mtf, 595 std::string(R"( 596 3H3S4T5-------1H1S1T4-------D2 597 2H2S2T6-------D2 598 10H1S1T7------D3 599 )") 600 .substr(1), 601 /* print_timestamp = */ true); 602 603 EXPECT_TRUE(mtf.ValueFromRank(1, &value)); 604 EXPECT_EQ(10u, value); 605 } 606 607 TEST(MoveToFront, Remove) { 608 MoveToFrontTester mtf; 609 610 EXPECT_FALSE(mtf.Remove(1)); 611 EXPECT_EQ(0u, mtf.GetTotalNodeCount()); 612 613 EXPECT_TRUE(mtf.Insert(1)); 614 EXPECT_TRUE(mtf.Insert(2)); 615 EXPECT_TRUE(mtf.Insert(3)); 616 617 CheckTree(mtf, 618 std::string(R"( 619 2H2S3T2-------1H1S1T1-------D2 620 3H1S1T3-------D2 621 )") 622 .substr(1), 623 /* print_timestamp = */ true); 624 625 EXPECT_EQ(1u, mtf.GetNodeHandle(1)); 626 EXPECT_EQ(3u, mtf.GetTotalNodeCount()); 627 EXPECT_TRUE(mtf.Remove(1)); 628 EXPECT_EQ(3u, mtf.GetTotalNodeCount()); 629 630 CheckTree(mtf, 631 std::string(R"( 632 2H2S2T2-------D1 633 3H1S1T3-------D2 634 )") 635 .substr(1), 636 /* print_timestamp = */ true); 637 638 uint32_t value = 0; 639 EXPECT_TRUE(mtf.ValueFromRank(2, &value)); 640 EXPECT_EQ(2u, value); 641 642 CheckTree(mtf, 643 std::string(R"( 644 3H2S2T3-------D1 645 2H1S1T4-------D2 646 )") 647 .substr(1), 648 /* print_timestamp = */ true); 649 650 EXPECT_TRUE(mtf.Insert(1)); 651 EXPECT_EQ(1u, mtf.GetNodeHandle(1)); 652 EXPECT_EQ(3u, mtf.GetTotalNodeCount()); 653 } 654 655 TEST(MoveToFront, LargerScale) { 656 MoveToFrontTester mtf; 657 uint32_t value = 0; 658 uint32_t rank = 0; 659 660 for (uint32_t i = 1; i < 1000; ++i) { 661 ASSERT_TRUE(mtf.Insert(i)); 662 ASSERT_EQ(i, mtf.GetSize()); 663 664 ASSERT_TRUE(mtf.RankFromValue(i, &rank)); 665 ASSERT_EQ(1u, rank); 666 667 ASSERT_TRUE(mtf.ValueFromRank(1, &value)); 668 ASSERT_EQ(i, value); 669 } 670 671 ASSERT_TRUE(mtf.ValueFromRank(999, &value)); 672 ASSERT_EQ(1u, value); 673 674 ASSERT_TRUE(mtf.ValueFromRank(999, &value)); 675 ASSERT_EQ(2u, value); 676 677 ASSERT_TRUE(mtf.ValueFromRank(999, &value)); 678 ASSERT_EQ(3u, value); 679 680 ASSERT_TRUE(mtf.ValueFromRank(999, &value)); 681 ASSERT_EQ(4u, value); 682 683 ASSERT_TRUE(mtf.ValueFromRank(999, &value)); 684 ASSERT_EQ(5u, value); 685 686 ASSERT_TRUE(mtf.ValueFromRank(999, &value)); 687 ASSERT_EQ(6u, value); 688 689 ASSERT_TRUE(mtf.ValueFromRank(101, &value)); 690 ASSERT_EQ(905u, value); 691 692 ASSERT_TRUE(mtf.ValueFromRank(101, &value)); 693 ASSERT_EQ(906u, value); 694 695 ASSERT_TRUE(mtf.ValueFromRank(101, &value)); 696 ASSERT_EQ(907u, value); 697 698 ASSERT_TRUE(mtf.ValueFromRank(201, &value)); 699 ASSERT_EQ(805u, value); 700 701 ASSERT_TRUE(mtf.ValueFromRank(201, &value)); 702 ASSERT_EQ(806u, value); 703 704 ASSERT_TRUE(mtf.ValueFromRank(201, &value)); 705 ASSERT_EQ(807u, value); 706 707 ASSERT_TRUE(mtf.ValueFromRank(301, &value)); 708 ASSERT_EQ(705u, value); 709 710 ASSERT_TRUE(mtf.ValueFromRank(301, &value)); 711 ASSERT_EQ(706u, value); 712 713 ASSERT_TRUE(mtf.ValueFromRank(301, &value)); 714 ASSERT_EQ(707u, value); 715 716 ASSERT_TRUE(mtf.RankFromValue(605, &rank)); 717 ASSERT_EQ(401u, rank); 718 719 ASSERT_TRUE(mtf.RankFromValue(606, &rank)); 720 ASSERT_EQ(401u, rank); 721 722 ASSERT_TRUE(mtf.RankFromValue(607, &rank)); 723 ASSERT_EQ(401u, rank); 724 725 ASSERT_TRUE(mtf.ValueFromRank(1, &value)); 726 ASSERT_EQ(607u, value); 727 728 ASSERT_TRUE(mtf.ValueFromRank(2, &value)); 729 ASSERT_EQ(606u, value); 730 731 ASSERT_TRUE(mtf.ValueFromRank(3, &value)); 732 ASSERT_EQ(605u, value); 733 734 ASSERT_TRUE(mtf.ValueFromRank(4, &value)); 735 ASSERT_EQ(707u, value); 736 737 ASSERT_TRUE(mtf.ValueFromRank(5, &value)); 738 ASSERT_EQ(706u, value); 739 740 ASSERT_TRUE(mtf.ValueFromRank(6, &value)); 741 ASSERT_EQ(705u, value); 742 743 ASSERT_TRUE(mtf.ValueFromRank(7, &value)); 744 ASSERT_EQ(807u, value); 745 746 ASSERT_TRUE(mtf.ValueFromRank(8, &value)); 747 ASSERT_EQ(806u, value); 748 749 ASSERT_TRUE(mtf.ValueFromRank(9, &value)); 750 ASSERT_EQ(805u, value); 751 752 ASSERT_TRUE(mtf.ValueFromRank(10, &value)); 753 ASSERT_EQ(907u, value); 754 755 ASSERT_TRUE(mtf.ValueFromRank(11, &value)); 756 ASSERT_EQ(906u, value); 757 758 ASSERT_TRUE(mtf.ValueFromRank(12, &value)); 759 ASSERT_EQ(905u, value); 760 761 ASSERT_TRUE(mtf.ValueFromRank(13, &value)); 762 ASSERT_EQ(6u, value); 763 764 ASSERT_TRUE(mtf.ValueFromRank(14, &value)); 765 ASSERT_EQ(5u, value); 766 767 ASSERT_TRUE(mtf.ValueFromRank(15, &value)); 768 ASSERT_EQ(4u, value); 769 770 ASSERT_TRUE(mtf.ValueFromRank(16, &value)); 771 ASSERT_EQ(3u, value); 772 773 ASSERT_TRUE(mtf.ValueFromRank(17, &value)); 774 ASSERT_EQ(2u, value); 775 776 ASSERT_TRUE(mtf.ValueFromRank(18, &value)); 777 ASSERT_EQ(1u, value); 778 779 ASSERT_TRUE(mtf.ValueFromRank(19, &value)); 780 ASSERT_EQ(999u, value); 781 782 ASSERT_TRUE(mtf.ValueFromRank(20, &value)); 783 ASSERT_EQ(998u, value); 784 785 ASSERT_TRUE(mtf.ValueFromRank(21, &value)); 786 ASSERT_EQ(997u, value); 787 788 ASSERT_TRUE(mtf.RankFromValue(997, &rank)); 789 ASSERT_EQ(1u, rank); 790 791 ASSERT_TRUE(mtf.RankFromValue(998, &rank)); 792 ASSERT_EQ(2u, rank); 793 794 ASSERT_TRUE(mtf.RankFromValue(996, &rank)); 795 ASSERT_EQ(22u, rank); 796 797 ASSERT_TRUE(mtf.Remove(995)); 798 799 ASSERT_TRUE(mtf.RankFromValue(994, &rank)); 800 ASSERT_EQ(23u, rank); 801 802 for (uint32_t i = 10; i < 1000; ++i) { 803 if (i != 995) { 804 ASSERT_TRUE(mtf.Remove(i)); 805 } else { 806 ASSERT_FALSE(mtf.Remove(i)); 807 } 808 } 809 810 CheckTree(mtf, 811 std::string(R"( 812 6H4S9T1029----8H2S3T8-------7H1S1T7-------D3 813 9H1S1T9-------D3 814 2H3S5T1033----4H2S3T1031----5H1S1T1030----D4 815 3H1S1T1032----D4 816 1H1S1T1034----D3 817 )") 818 .substr(1), 819 /* print_timestamp = */ true); 820 821 ASSERT_TRUE(mtf.Insert(1000)); 822 ASSERT_TRUE(mtf.ValueFromRank(1, &value)); 823 ASSERT_EQ(1000u, value); 824 } 825 826 } // namespace 827 } // namespace comp 828 } // namespace spvtools 829