1 //===-- Unittests for a freetrie --------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "src/__support/freetrie.h"
12 #include "test/UnitTest/Test.h"
14 using LIBC_NAMESPACE::Block
;
15 using LIBC_NAMESPACE::FreeTrie
;
16 using LIBC_NAMESPACE::cpp::byte
;
17 using LIBC_NAMESPACE::cpp::optional
;
19 TEST(LlvmLibcFreeTrie
, FindBestFitRoot
) {
20 FreeTrie
trie({0, 4096});
21 EXPECT_EQ(trie
.find_best_fit(123), static_cast<FreeTrie::Node
*>(nullptr));
24 optional
<Block
*> maybeBlock
= Block::init(mem
);
25 ASSERT_TRUE(maybeBlock
.has_value());
26 Block
*block
= *maybeBlock
;
29 FreeTrie::Node
*root
= trie
.find_best_fit(0);
30 ASSERT_EQ(root
->block(), block
);
31 EXPECT_EQ(trie
.find_best_fit(block
->inner_size() - 1), root
);
32 EXPECT_EQ(trie
.find_best_fit(block
->inner_size()), root
);
33 EXPECT_EQ(trie
.find_best_fit(block
->inner_size() + 1),
34 static_cast<FreeTrie::Node
*>(nullptr));
35 EXPECT_EQ(trie
.find_best_fit(4095), static_cast<FreeTrie::Node
*>(nullptr));
38 TEST(LlvmLibcFreeTrie
, FindBestFitLower
) {
40 optional
<Block
*> maybeBlock
= Block::init(mem
);
41 ASSERT_TRUE(maybeBlock
.has_value());
42 Block
*lower
= *maybeBlock
;
43 maybeBlock
= lower
->split(512);
44 ASSERT_TRUE(maybeBlock
.has_value());
45 Block
*root
= *maybeBlock
;
47 FreeTrie
trie({0, 4096});
51 EXPECT_EQ(trie
.find_best_fit(0)->block(), lower
);
54 TEST(LlvmLibcFreeTrie
, FindBestFitUpper
) {
56 optional
<Block
*> maybeBlock
= Block::init(mem
);
57 ASSERT_TRUE(maybeBlock
.has_value());
58 Block
*root
= *maybeBlock
;
59 maybeBlock
= root
->split(512);
60 ASSERT_TRUE(maybeBlock
.has_value());
61 Block
*upper
= *maybeBlock
;
63 FreeTrie
trie({0, 4096});
67 EXPECT_EQ(trie
.find_best_fit(root
->inner_size() + 1)->block(), upper
);
68 // The upper subtrie should be skipped if it could not contain a better fit.
69 EXPECT_EQ(trie
.find_best_fit(root
->inner_size() - 1)->block(), root
);
72 TEST(LlvmLibcFreeTrie
, FindBestFitLowerAndUpper
) {
74 optional
<Block
*> maybeBlock
= Block::init(mem
);
75 ASSERT_TRUE(maybeBlock
.has_value());
76 Block
*root
= *maybeBlock
;
77 maybeBlock
= root
->split(1024);
78 ASSERT_TRUE(maybeBlock
.has_value());
79 Block
*lower
= *maybeBlock
;
80 maybeBlock
= lower
->split(128);
81 ASSERT_TRUE(maybeBlock
.has_value());
82 Block
*upper
= *maybeBlock
;
84 FreeTrie
trie({0, 4096});
89 // The lower subtrie is examined first.
90 EXPECT_EQ(trie
.find_best_fit(0)->block(), lower
);
91 // The upper subtrie is examined if there are no fits found in the upper
93 EXPECT_EQ(trie
.find_best_fit(2048)->block(), upper
);
96 TEST(LlvmLibcFreeTrie
, Remove
) {
98 optional
<Block
*> maybeBlock
= Block::init(mem
);
99 ASSERT_TRUE(maybeBlock
.has_value());
100 Block
*small1
= *maybeBlock
;
101 maybeBlock
= small1
->split(512);
102 ASSERT_TRUE(maybeBlock
.has_value());
103 Block
*small2
= *maybeBlock
;
104 maybeBlock
= small2
->split(512);
105 ASSERT_TRUE(maybeBlock
.has_value());
106 ASSERT_EQ(small1
->inner_size(), small2
->inner_size());
107 Block
*large
= *maybeBlock
;
109 // Removing the root empties the trie.
110 FreeTrie
trie({0, 4096});
112 FreeTrie::Node
*large_node
= trie
.find_best_fit(0);
113 ASSERT_EQ(large_node
->block(), large
);
114 trie
.remove(large_node
);
115 ASSERT_TRUE(trie
.empty());
117 // Removing the head of a trie list preserves the trie structure.
121 trie
.remove(trie
.find_best_fit(small1
->inner_size()));
122 EXPECT_EQ(trie
.find_best_fit(large
->inner_size())->block(), large
);
123 trie
.remove(trie
.find_best_fit(small1
->inner_size()));
124 EXPECT_EQ(trie
.find_best_fit(large
->inner_size())->block(), large
);