Skip to content

Commit a56ce83

Browse files
committed
add complex forest tests
1 parent f4ec6ab commit a56ce83

File tree

1 file changed

+180
-10
lines changed

1 file changed

+180
-10
lines changed

hhds/tests/forest_correctness.cpp

+180-10
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void test_tree_traversal_with_subtrees() {
8181

8282
// build trees
8383
auto child1 = main_tree.add_child(main_tree.get_root(), 2);
84-
main_tree.add_child(main_tree.get_root(), 3); // child2
84+
main_tree.add_child(main_tree.get_root(), 3); // No need to store child2
8585

8686
sub_tree.add_child(sub_tree.get_root(), 11);
8787
sub_tree.add_child(sub_tree.get_root(), 12);
@@ -92,27 +92,187 @@ void test_tree_traversal_with_subtrees() {
9292
// test traversal with subtree following
9393
int count = 0;
9494
std::vector<int> visited_values;
95-
std::cout << "Starting traversal...\n";
9695

9796
auto range = main_tree.pre_order(main_tree.get_root(), true);
9897
for (auto it = range.begin(); it != range.end(); ++it) {
99-
int value = it.get_data();
100-
visited_values.push_back(value);
101-
std::cout << "Visiting node with value: " << value << std::endl;
98+
visited_values.push_back(it.get_data());
10299
count++;
103-
if (count > 10) { // Safety check
104-
std::cout << "Possible infinite loop detected\n";
105-
break;
106-
}
107100
}
108101

109102
// should visit: 1, 2, 10, 11, 12, 3
110103
I(count == 6, "Pre-order traversal with subtrees should visit 6 nodes");
111-
I(visited_values == std::vector<int>{1, 2, 10, 11, 12, 3},
104+
105+
std::vector<int> expected = {1, 2, 10, 11, 12, 3};
106+
I(visited_values == expected,
112107
"Pre-order traversal with subtrees should visit nodes in the correct order");
113108
}
114109

110+
void test_complex_forest_operations() {
111+
hhds::Forest<int> forest;
112+
113+
// create multiple trees
114+
auto main_tree_ref = forest.create_tree(1);
115+
auto sub_tree1_ref = forest.create_tree(1000);
116+
auto sub_tree2_ref = forest.create_tree(2000);
117+
auto sub_tree3_ref = forest.create_tree(3000);
118+
119+
auto& main_tree = forest.get_tree(main_tree_ref);
120+
auto& sub_tree1 = forest.get_tree(sub_tree1_ref);
121+
auto& sub_tree2 = forest.get_tree(sub_tree2_ref);
122+
auto& sub_tree3 = forest.get_tree(sub_tree3_ref);
123+
124+
// build tree structures
125+
std::vector<hhds::Tree_pos> main_nodes;
126+
std::vector<hhds::Tree_pos> sub1_nodes;
127+
std::vector<hhds::Tree_pos> sub2_nodes;
128+
std::vector<hhds::Tree_pos> sub3_nodes;
129+
130+
// create a deep main tree with multiple branches
131+
main_nodes.push_back(main_tree.get_root());
132+
for (int i = 0; i < 100; ++i) {
133+
auto parent = main_nodes[i / 3];
134+
auto new_node = main_tree.add_child(parent, i + 2);
135+
main_nodes.push_back(new_node);
136+
}
137+
138+
// create wide sub_tree1 with many siblings
139+
sub1_nodes.push_back(sub_tree1.get_root());
140+
auto sub1_parent = sub_tree1.get_root();
141+
for (int i = 0; i < 50; ++i) {
142+
auto new_node = sub_tree1.add_child(sub1_parent, 1100 + i);
143+
sub1_nodes.push_back(new_node);
144+
}
145+
146+
// create balanced sub_tree2
147+
sub2_nodes.push_back(sub_tree2.get_root());
148+
for (int i = 0; i < 32; ++i) {
149+
auto parent = sub2_nodes[i];
150+
auto left = sub_tree2.add_child(parent, 2100 + i*2);
151+
auto right = sub_tree2.add_child(parent, 2100 + i*2 + 1);
152+
sub2_nodes.push_back(left);
153+
sub2_nodes.push_back(right);
154+
}
155+
156+
// create deep chain in sub_tree3
157+
sub3_nodes.push_back(sub_tree3.get_root());
158+
auto current = sub_tree3.get_root();
159+
for (int i = 0; i < 100; ++i) {
160+
auto new_node = sub_tree3.add_child(current, 3100 + i);
161+
sub3_nodes.push_back(new_node);
162+
current = new_node;
163+
}
164+
165+
// create complex reference patterns
166+
for (int i = 0; i < main_nodes.size(); i += 10) {
167+
main_tree.add_subtree_ref(main_nodes[i], sub_tree1_ref);
168+
}
169+
170+
for (int i = 0; i < sub1_nodes.size(); i += 5) {
171+
sub_tree1.add_subtree_ref(sub1_nodes[i], sub_tree2_ref);
172+
}
173+
174+
for (int i = 0; i < sub2_nodes.size(); i += 3) {
175+
sub_tree2.add_subtree_ref(sub2_nodes[i], sub_tree3_ref);
176+
}
177+
178+
// test reference counting
179+
bool deleted = forest.delete_tree(sub_tree3_ref);
180+
I(!deleted, "Should not be able to delete heavily referenced tree");
181+
182+
// test traversal with subtree references
183+
int node_count = 0;
184+
std::set<int> unique_values;
185+
186+
auto range = main_tree.pre_order(main_tree.get_root(), true);
187+
for (auto it = range.begin(); it != range.end(); ++it) {
188+
node_count++;
189+
unique_values.insert(it.get_data());
190+
191+
I(node_count <= 10000, "Possible infinite loop in traversal");
192+
}
193+
194+
I(node_count > 500, "Should visit at least 500 nodes in large tree traversal");
195+
I(unique_values.size() > 200, "Should see at least 200 unique values");
196+
197+
// tst bulk deletions
198+
for (int i = main_nodes.size() - 1; i >= 0; i -= 10) {
199+
if (i < main_nodes.size()) {
200+
main_tree.delete_leaf(main_nodes[i]);
201+
}
202+
}
203+
204+
// verify reference counts
205+
deleted = forest.delete_tree(sub_tree1_ref);
206+
I(!deleted, "Should still not be able to delete referenced tree");
207+
}
208+
209+
void test_edge_cases() {
210+
hhds::Forest<int> forest;
211+
212+
// test creation of more trees
213+
std::vector<hhds::Tree_pos> tree_refs;
214+
for (int i = 0; i < 5; ++i) {
215+
auto ref = forest.create_tree(i);
216+
tree_refs.push_back(ref);
217+
218+
auto& tree = forest.get_tree(ref);
219+
I(tree.get_data(tree.get_root()) == i, "Tree creation verification failed");
220+
}
221+
222+
// create chain of references with two children per tree
223+
for (size_t i = 0; i < tree_refs.size() - 1; ++i) {
224+
auto& current_tree = forest.get_tree(tree_refs[i]);
225+
auto root = current_tree.get_root();
226+
I(current_tree.get_data(root) == i, "Root data verification failed");
227+
228+
for (int j = 0; j < 2; ++j) {
229+
auto child = current_tree.add_child(root, i * 10 + j);
230+
I(current_tree.get_data(child) == i * 10 + j, "Child creation verification failed");
231+
I(current_tree.is_leaf(child), "New node should be a leaf");
232+
233+
if (j == 0) {
234+
current_tree.add_subtree_ref(child, tree_refs[(i + 1) % tree_refs.size()]);
235+
}
236+
}
237+
}
238+
239+
// create single circular reference
240+
auto& last_tree = forest.get_tree(tree_refs.back());
241+
auto last_child = last_tree.add_child(last_tree.get_root(), 100);
242+
I(last_tree.get_data(last_child) == 100, "Last child creation verification failed");
243+
last_tree.add_subtree_ref(last_child, tree_refs[0]);
244+
245+
// add a few more leaf nodes to existing trees
246+
for (size_t i = 0; i < tree_refs.size(); i += 2) { // Every other tree
247+
auto& tree = forest.get_tree(tree_refs[i]);
248+
tree.add_child(tree.get_root(), i * 20);
249+
}
250+
251+
// test traversal
252+
int count = 0;
253+
std::set<int> unique_values;
254+
auto& first_tree = forest.get_tree(tree_refs[0]);
255+
256+
for (auto it = first_tree.pre_order(first_tree.get_root(), true).begin();
257+
it != first_tree.pre_order(first_tree.get_root(), true).end(); ++it) {
258+
count++;
259+
unique_values.insert(it.get_data());
260+
I(count <= 32, "Traversal count exceeded expected maximum");
261+
}
262+
263+
I(count > 5, "Should visit at least 5 nodes in traversal");
264+
I(unique_values.size() > 3, "Should see at least 3 unique values");
265+
266+
// try to delete trees
267+
for (auto ref : tree_refs) {
268+
bool deleted = forest.delete_tree(ref);
269+
I(!deleted, "Should not be able to delete referenced trees");
270+
}
271+
}
272+
115273
int main() {
274+
std::cout << "\nStarting forest correctness tests...\n\n";
275+
116276
test_basic_forest_operations();
117277
std::cout << "Basic forest operations test passed\n";
118278

@@ -122,5 +282,15 @@ int main() {
122282
test_tree_traversal_with_subtrees();
123283
std::cout << "Tree traversal with subtrees test passed\n";
124284

285+
std::cout << "\nStarting large-scale tests...\n";
286+
287+
test_complex_forest_operations();
288+
std::cout << "Complex forest operations test passed\n";
289+
290+
test_edge_cases();
291+
std::cout << "Edge cases test passed\n";
292+
293+
std::cout << "\nAll forest correctness tests passed successfully!\n";
294+
125295
return 0;
126296
}

0 commit comments

Comments
 (0)