TestIntrusiveRedBlackTree.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibTest/TestCase.h>
  7. #include <AK/IntrusiveRedBlackTree.h>
  8. #include <AK/NonnullOwnPtrVector.h>
  9. #include <AK/Random.h>
  10. class IntrusiveTest {
  11. public:
  12. IntrusiveTest(int value)
  13. : m_some_value(value)
  14. {
  15. }
  16. IntrusiveRedBlackTreeNode<int, IntrusiveTest, RawPtr<IntrusiveTest>> m_tree_node;
  17. int m_some_value;
  18. };
  19. using IntrusiveRBTree = IntrusiveRedBlackTree<&IntrusiveTest::m_tree_node>;
  20. TEST_CASE(construct)
  21. {
  22. IntrusiveRBTree empty;
  23. EXPECT(empty.is_empty());
  24. EXPECT(empty.size() == 0);
  25. }
  26. TEST_CASE(ints)
  27. {
  28. IntrusiveRBTree test;
  29. IntrusiveTest first { 10 };
  30. test.insert(1, first);
  31. IntrusiveTest second { 20 };
  32. test.insert(3, second);
  33. IntrusiveTest third { 30 };
  34. test.insert(2, third);
  35. EXPECT_EQ(test.size(), 3u);
  36. EXPECT_EQ(test.find(3)->m_some_value, 20);
  37. EXPECT_EQ(test.find(2)->m_some_value, 30);
  38. EXPECT_EQ(test.find(1)->m_some_value, 10);
  39. EXPECT(!test.remove(4));
  40. EXPECT(test.remove(2));
  41. EXPECT(test.remove(1));
  42. EXPECT(test.remove(3));
  43. EXPECT_EQ(test.size(), 0u);
  44. }
  45. TEST_CASE(largest_smaller_than)
  46. {
  47. IntrusiveRBTree test;
  48. IntrusiveTest first { 10 };
  49. test.insert(1, first);
  50. IntrusiveTest second { 20 };
  51. test.insert(11, second);
  52. IntrusiveTest third { 30 };
  53. test.insert(21, third);
  54. EXPECT_EQ(test.size(), 3u);
  55. EXPECT_EQ(test.find_largest_not_above(3)->m_some_value, 10);
  56. EXPECT_EQ(test.find_largest_not_above(17)->m_some_value, 20);
  57. EXPECT_EQ(test.find_largest_not_above(22)->m_some_value, 30);
  58. EXPECT_EQ(test.find_largest_not_above(-5), nullptr);
  59. VERIFY(test.remove(1));
  60. VERIFY(test.remove(11));
  61. VERIFY(test.remove(21));
  62. }
  63. TEST_CASE(key_ordered_iteration)
  64. {
  65. constexpr auto amount = 10000;
  66. IntrusiveRBTree test;
  67. Vector<NonnullOwnPtr<IntrusiveTest>> m_entries;
  68. Array<int, amount> keys {};
  69. // generate random key order
  70. for (int i = 0; i < amount; i++) {
  71. keys[i] = i;
  72. }
  73. for (size_t i = 0; i < amount; i++) {
  74. swap(keys[i], keys[get_random<size_t>() % amount]);
  75. }
  76. // insert random keys
  77. for (size_t i = 0; i < amount; i++) {
  78. auto entry = make<IntrusiveTest>(keys[i]);
  79. test.insert(keys[i], *entry);
  80. m_entries.append(move(entry));
  81. }
  82. // check key-ordered iteration
  83. int index = 0;
  84. for (auto& value : test) {
  85. EXPECT(value.m_some_value == index++);
  86. }
  87. // ensure we can remove all of them (aka, tree structure is not destroyed somehow)
  88. for (size_t i = 0; i < amount; i++) {
  89. EXPECT(test.remove(i));
  90. }
  91. }
  92. TEST_CASE(clear)
  93. {
  94. IntrusiveRBTree test;
  95. Vector<NonnullOwnPtr<IntrusiveTest>> m_entries;
  96. for (size_t i = 0; i < 1000; i++) {
  97. auto entry = make<IntrusiveTest>(i);
  98. test.insert(i, *entry);
  99. m_entries.append(move(entry));
  100. }
  101. test.clear();
  102. EXPECT_EQ(test.size(), 0u);
  103. }
  104. class IntrusiveRefPtrTest : public RefCounted<IntrusiveRefPtrTest> {
  105. public:
  106. IntrusiveRefPtrTest()
  107. {
  108. }
  109. IntrusiveRedBlackTreeNode<int, IntrusiveRefPtrTest, RefPtr<IntrusiveRefPtrTest>> m_tree_node;
  110. };
  111. using IntrusiveRefPtrRBTree = IntrusiveRedBlackTree<&IntrusiveRefPtrTest::m_tree_node>;
  112. TEST_CASE(intrusive_ref_ptr_no_ref_leaks)
  113. {
  114. auto item = adopt_ref(*new IntrusiveRefPtrTest());
  115. EXPECT_EQ(1u, item->ref_count());
  116. IntrusiveRefPtrRBTree ref_tree;
  117. ref_tree.insert(0, *item);
  118. EXPECT_EQ(2u, item->ref_count());
  119. ref_tree.remove(0);
  120. EXPECT_EQ(1u, item->ref_count());
  121. }
  122. TEST_CASE(intrusive_ref_ptr_clear)
  123. {
  124. auto item = adopt_ref(*new IntrusiveRefPtrTest());
  125. EXPECT_EQ(1u, item->ref_count());
  126. IntrusiveRefPtrRBTree ref_tree;
  127. ref_tree.insert(0, *item);
  128. EXPECT_EQ(2u, item->ref_count());
  129. ref_tree.clear();
  130. EXPECT_EQ(1u, item->ref_count());
  131. }
  132. TEST_CASE(intrusive_ref_ptr_destructor)
  133. {
  134. auto item = adopt_ref(*new IntrusiveRefPtrTest());
  135. EXPECT_EQ(1u, item->ref_count());
  136. {
  137. IntrusiveRefPtrRBTree ref_tree;
  138. ref_tree.insert(0, *item);
  139. EXPECT_EQ(2u, item->ref_count());
  140. }
  141. EXPECT_EQ(1u, item->ref_count());
  142. }
  143. class IntrusiveNonnullRefPtrTest : public RefCounted<IntrusiveNonnullRefPtrTest> {
  144. public:
  145. IntrusiveNonnullRefPtrTest()
  146. {
  147. }
  148. IntrusiveRedBlackTreeNode<int, IntrusiveNonnullRefPtrTest, NonnullRefPtr<IntrusiveNonnullRefPtrTest>> m_tree_node;
  149. };
  150. using IntrusiveNonnullRefPtrRBTree = IntrusiveRedBlackTree<&IntrusiveNonnullRefPtrTest::m_tree_node>;
  151. TEST_CASE(intrusive_nonnull_ref_ptr_intrusive)
  152. {
  153. auto item = adopt_ref(*new IntrusiveNonnullRefPtrTest());
  154. EXPECT_EQ(1u, item->ref_count());
  155. IntrusiveNonnullRefPtrRBTree nonnull_ref_tree;
  156. nonnull_ref_tree.insert(0, *item);
  157. EXPECT_EQ(2u, item->ref_count());
  158. EXPECT(!nonnull_ref_tree.is_empty());
  159. nonnull_ref_tree.remove(0);
  160. EXPECT_EQ(1u, item->ref_count());
  161. EXPECT(nonnull_ref_tree.is_empty());
  162. }