Skip to content

Commit a0af17b

Browse files
jeromekellehermergify-bot
authored and
mergify-bot
committed
Refactor node traversal tests
Change timeasc and timedesc to keep the tree ordering within a timeslice rather than sorting by node ID (potentially breaking) Closes #1776 Closes #1725
1 parent 0a98866 commit a0af17b

File tree

11 files changed

+1044
-458
lines changed

11 files changed

+1044
-458
lines changed

c/tests/test_trees.c

+230-5
Original file line numberDiff line numberDiff line change
@@ -3863,8 +3863,8 @@ test_single_tree_iter_depths(void)
38633863
const char *edges = "0 6 4 0,1\n"
38643864
"0 6 5 2,3\n"
38653865
"0 6 6 4,5\n";
3866-
unsigned int depths[] = { 2, 2, 2, 2, 1, 1, 0 };
3867-
tsk_size_t depth;
3866+
int depths[] = { 2, 2, 2, 2, 1, 1, 0 };
3867+
int depth;
38683868
tsk_treeseq_t ts;
38693869
tsk_tree_t tree;
38703870
tsk_id_t u;
@@ -3878,14 +3878,14 @@ test_single_tree_iter_depths(void)
38783878
CU_ASSERT_EQUAL(tsk_treeseq_get_num_nodes(&ts), num_nodes);
38793879

38803880
for (u = 0; u < (tsk_id_t) num_nodes; u++) {
3881-
ret = tsk_tree_depth(&tree, u, &depth);
3881+
ret = tsk_tree_get_depth(&tree, u, &depth);
38823882
CU_ASSERT_EQUAL(ret, 0);
38833883
CU_ASSERT_EQUAL(depth, depths[u]);
38843884
}
38853885

3886-
ret = tsk_tree_depth(&tree, (tsk_id_t) num_nodes + 1, &depth);
3886+
ret = tsk_tree_get_depth(&tree, (tsk_id_t) num_nodes + 1, &depth);
38873887
CU_ASSERT_EQUAL(ret, TSK_ERR_NODE_OUT_OF_BOUNDS);
3888-
ret = tsk_tree_depth(&tree, TSK_NULL, &depth);
3888+
ret = tsk_tree_get_depth(&tree, TSK_NULL, &depth);
38893889
CU_ASSERT_EQUAL(ret, TSK_ERR_NODE_OUT_OF_BOUNDS);
38903890

38913891
ret = tsk_tree_next(&tree);
@@ -5017,6 +5017,225 @@ test_non_sample_leaf_sample_lists(void)
50175017
tsk_tree_free(&t);
50185018
}
50195019

5020+
static void
5021+
test_virtual_root_properties(void)
5022+
{
5023+
int ret;
5024+
tsk_treeseq_t ts;
5025+
tsk_tree_t t;
5026+
int depth;
5027+
double time;
5028+
tsk_id_t node;
5029+
5030+
tsk_treeseq_from_text(&ts, 1, single_tree_ex_nodes, single_tree_ex_edges, NULL, NULL,
5031+
NULL, NULL, NULL, 0);
5032+
5033+
ret = tsk_tree_init(&t, &ts, 0);
5034+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5035+
ret = tsk_tree_first(&t);
5036+
CU_ASSERT_EQUAL_FATAL(ret, 1);
5037+
5038+
CU_ASSERT_EQUAL_FATAL(tsk_tree_get_depth(&t, t.virtual_root, &depth), 0)
5039+
CU_ASSERT_EQUAL_FATAL(depth, -1);
5040+
5041+
CU_ASSERT_EQUAL_FATAL(tsk_tree_get_time(&t, t.virtual_root, &time), 0)
5042+
CU_ASSERT_TRUE(isinf(time));
5043+
5044+
CU_ASSERT_EQUAL_FATAL(tsk_tree_get_mrca(&t, t.virtual_root, 0, &node), 0)
5045+
CU_ASSERT_EQUAL(node, t.virtual_root);
5046+
5047+
CU_ASSERT_EQUAL_FATAL(tsk_tree_get_mrca(&t, 0, t.virtual_root, &node), 0)
5048+
CU_ASSERT_EQUAL(node, t.virtual_root);
5049+
5050+
CU_ASSERT_EQUAL_FATAL(tsk_tree_get_parent(&t, t.virtual_root, &node), 0)
5051+
CU_ASSERT_EQUAL(node, TSK_NULL);
5052+
5053+
/* The definition of "descendant" is that node v is on the path from
5054+
* u to a root. Since there is no parent link from roots to the
5055+
* virtual_root, it's consistent with this definition to return false
5056+
* for every node. */
5057+
CU_ASSERT_FALSE(tsk_tree_is_descendant(&t, 0, t.virtual_root));
5058+
CU_ASSERT_FALSE(
5059+
tsk_tree_is_descendant(&t, t.left_child[t.virtual_root], t.virtual_root));
5060+
CU_ASSERT_FALSE(tsk_tree_is_descendant(&t, t.virtual_root, 0));
5061+
/* The virtual_root *is* a descendent of itself, though. This is
5062+
* consistent with other nodes that are not "in" the tree being
5063+
* descendents of themselves, despite not being roots in the tree. */
5064+
CU_ASSERT_TRUE(tsk_tree_is_descendant(&t, t.virtual_root, t.virtual_root));
5065+
5066+
CU_ASSERT_FALSE(tsk_tree_is_sample(&t, t.virtual_root));
5067+
5068+
tsk_tree_free(&t);
5069+
tsk_treeseq_free(&ts);
5070+
}
5071+
5072+
/*=======================================================
5073+
* Tree traversals
5074+
*=======================================================*/
5075+
5076+
static void
5077+
verify_node_lists(tsk_size_t n, tsk_id_t *l1, tsk_id_t *l2)
5078+
{
5079+
tsk_size_t j;
5080+
5081+
for (j = 0; j < n; j++) {
5082+
/* printf("%d %d\n", l1[j], l2[j]); */
5083+
CU_ASSERT_EQUAL(l1[j], l2[j]);
5084+
}
5085+
}
5086+
5087+
static void
5088+
test_single_tree_traversal(void)
5089+
{
5090+
int ret;
5091+
tsk_treeseq_t ts;
5092+
tsk_tree_t t;
5093+
tsk_size_t num_nodes = 7;
5094+
tsk_id_t preorder[] = { 6, 4, 0, 1, 5, 2, 3 };
5095+
tsk_id_t preorder_vr[] = { 7, 6, 4, 0, 1, 5, 2, 3 };
5096+
tsk_id_t postorder[] = { 0, 1, 4, 2, 3, 5, 6 };
5097+
tsk_id_t postorder_vr[] = { 0, 1, 4, 2, 3, 5, 6, 7 };
5098+
tsk_id_t nodes[num_nodes + 1];
5099+
tsk_size_t n;
5100+
5101+
tsk_treeseq_from_text(&ts, 1, single_tree_ex_nodes, single_tree_ex_edges, NULL, NULL,
5102+
NULL, NULL, NULL, 0);
5103+
5104+
ret = tsk_tree_init(&t, &ts, 0);
5105+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5106+
ret = tsk_tree_first(&t);
5107+
CU_ASSERT_EQUAL_FATAL(ret, 1);
5108+
5109+
ret = tsk_tree_preorder(&t, -1, nodes, &n);
5110+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5111+
CU_ASSERT_EQUAL_FATAL(n, num_nodes);
5112+
verify_node_lists(n, nodes, preorder);
5113+
5114+
ret = tsk_tree_preorder(&t, t.virtual_root, nodes, &n);
5115+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5116+
CU_ASSERT_EQUAL_FATAL(n, num_nodes + 1);
5117+
verify_node_lists(n, nodes, preorder_vr);
5118+
5119+
ret = tsk_tree_preorder(&t, 5, nodes, &n);
5120+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5121+
CU_ASSERT_EQUAL_FATAL(n, 3);
5122+
verify_node_lists(n, nodes, preorder + 4);
5123+
5124+
ret = tsk_tree_postorder(&t, -1, nodes, &n);
5125+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5126+
CU_ASSERT_EQUAL_FATAL(n, num_nodes);
5127+
verify_node_lists(n, nodes, postorder);
5128+
5129+
ret = tsk_tree_postorder(&t, t.virtual_root, nodes, &n);
5130+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5131+
CU_ASSERT_EQUAL_FATAL(n, num_nodes + 1);
5132+
verify_node_lists(n, nodes, postorder_vr);
5133+
5134+
ret = tsk_tree_postorder(&t, 4, nodes, &n);
5135+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5136+
CU_ASSERT_EQUAL_FATAL(n, 3);
5137+
verify_node_lists(n, nodes, postorder);
5138+
5139+
/* Check errors */
5140+
ret = tsk_tree_preorder(&t, -2, nodes, &n);
5141+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_NODE_OUT_OF_BOUNDS);
5142+
ret = tsk_tree_preorder(&t, 8, nodes, &n);
5143+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_NODE_OUT_OF_BOUNDS);
5144+
5145+
ret = tsk_tree_postorder(&t, -2, nodes, &n);
5146+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_NODE_OUT_OF_BOUNDS);
5147+
ret = tsk_tree_postorder(&t, 8, nodes, &n);
5148+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_NODE_OUT_OF_BOUNDS);
5149+
5150+
tsk_tree_free(&t);
5151+
tsk_treeseq_free(&ts);
5152+
}
5153+
5154+
/* printed out in tree order.
5155+
0.90┊ ┊ 11 ┊ ┊
5156+
┊ ┊ ┏┻┓ ┊ ┊
5157+
0.80┊ 10 ┊ ┃ ┃ ┊ ┊
5158+
┊ ┏┻┓ ┊ ┃ ┃ ┊ ┊
5159+
0.40┊ 9 ┃ ┃ ┊ 9 ┃ ┃ ┊ 9 ┊
5160+
┊ ┏━┻┓ ┃ ┃ ┊ ┏━┻━┓ ┃ ┃ ┊ ┏━┻━━┓ ┊
5161+
0.30┊ ┃ ┃ ┃ ┃ ┊ ┃ 8 ┃ ┃ ┊ ┃ 8 ┊
5162+
┊ ┃ ┃ ┃ ┃ ┊ ┃ ┏┻┓ ┃ ┃ ┊ ┃ ┏┻┓ ┊
5163+
0.20┊ ┃ 7 ┃ ┃ ┊ 7 ┃ ┃ ┃ ┃ ┊ 7 ┃ ┃ ┊
5164+
┊ ┃ ┏┻┓ ┃ ┃ ┊ ┏┻┓ ┃ ┃ ┃ ┃ ┊ ┏━┻┓ ┃ ┃ ┊
5165+
0.10┊ ┃ ┃ ┃ ┃ ┃ ┊ ┃ ┃ ┃ ┃ ┃ ┃ ┊ ┃ 6 ┃ ┃ ┊
5166+
┊ ┃ ┃ ┃ ┃ ┃ ┊ ┃ ┃ ┃ ┃ ┃ ┃ ┊ ┃ ┏┻┓ ┃ ┃ ┊
5167+
0.00┊ 5 2 3 4 0 1 ┊ 3 4 1 2 0 5 ┊ 4 0 3 1 2 5 ┊
5168+
0 4 8 10
5169+
*/
5170+
5171+
static void
5172+
test_multiroot_tree_traversal(void)
5173+
{
5174+
int ret;
5175+
tsk_treeseq_t ts;
5176+
5177+
tsk_tree_t t;
5178+
tsk_id_t preorder[] = { 5, 9, 2, 7, 3, 4, 10, 0, 1 };
5179+
tsk_id_t preorder_vr[] = { 12, 5, 9, 2, 7, 3, 4, 10, 0, 1 };
5180+
tsk_id_t postorder[] = { 5, 2, 3, 4, 7, 9, 0, 1, 10 };
5181+
tsk_id_t postorder_vr[] = { 5, 2, 3, 4, 7, 9, 0, 1, 10, 12 };
5182+
tsk_id_t nodes[13];
5183+
tsk_size_t n;
5184+
5185+
tsk_treeseq_from_text(&ts, 10, multiroot_ex_nodes, multiroot_ex_edges, NULL, NULL,
5186+
NULL, NULL, NULL, 0);
5187+
5188+
ret = tsk_tree_init(&t, &ts, 0);
5189+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5190+
ret = tsk_tree_first(&t);
5191+
CU_ASSERT_EQUAL_FATAL(ret, 1);
5192+
5193+
ret = tsk_tree_preorder(&t, -1, nodes, &n);
5194+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5195+
CU_ASSERT_EQUAL_FATAL(n, 9);
5196+
verify_node_lists(n, nodes, preorder);
5197+
5198+
ret = tsk_tree_preorder(&t, t.virtual_root, nodes, &n);
5199+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5200+
CU_ASSERT_EQUAL_FATAL(n, 10);
5201+
verify_node_lists(n, nodes, preorder_vr);
5202+
5203+
ret = tsk_tree_preorder(&t, 10, nodes, &n);
5204+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5205+
CU_ASSERT_EQUAL_FATAL(n, 3);
5206+
verify_node_lists(n, nodes, preorder + 6);
5207+
5208+
ret = tsk_tree_postorder(&t, -1, nodes, &n);
5209+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5210+
CU_ASSERT_EQUAL_FATAL(n, 9);
5211+
verify_node_lists(n, nodes, postorder);
5212+
5213+
ret = tsk_tree_postorder(&t, t.virtual_root, nodes, &n);
5214+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5215+
CU_ASSERT_EQUAL_FATAL(n, 10);
5216+
verify_node_lists(n, nodes, postorder_vr);
5217+
5218+
ret = tsk_tree_postorder(&t, 10, nodes, &n);
5219+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5220+
CU_ASSERT_EQUAL_FATAL(n, 3);
5221+
verify_node_lists(n, nodes, postorder + 6);
5222+
5223+
/* Nodes that aren't "in" the tree have singleton traversal lists */
5224+
5225+
ret = tsk_tree_preorder(&t, 11, nodes, &n);
5226+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5227+
CU_ASSERT_EQUAL_FATAL(n, 1);
5228+
CU_ASSERT_EQUAL_FATAL(nodes[0], 11);
5229+
5230+
ret = tsk_tree_postorder(&t, 11, nodes, &n);
5231+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5232+
CU_ASSERT_EQUAL_FATAL(n, 1);
5233+
CU_ASSERT_EQUAL_FATAL(nodes[0], 11);
5234+
5235+
tsk_tree_free(&t);
5236+
tsk_treeseq_free(&ts);
5237+
}
5238+
50205239
/*=======================================================
50215240
* KC Distance tests.
50225241
*=======================================================*/
@@ -6405,6 +6624,12 @@ main(int argc, char **argv)
64056624
{ "test_internal_sample_sample_sets", test_internal_sample_sample_sets },
64066625
{ "test_non_sample_leaf_sample_lists", test_non_sample_leaf_sample_lists },
64076626

6627+
{ "test_virtual_root_properties", test_virtual_root_properties },
6628+
6629+
/* tree traversal orders */
6630+
{ "test_single_tree_traversal", test_single_tree_traversal },
6631+
{ "test_multiroot_tree_traversal", test_multiroot_tree_traversal },
6632+
64086633
/* KC distance tests */
64096634
{ "test_single_tree_kc", test_single_tree_kc },
64106635
{ "test_isolated_node_kc", test_isolated_node_kc },

c/tests/testlib.c

+14-14
Original file line numberDiff line numberDiff line change
@@ -309,20 +309,20 @@ const char *internal_sample_ex_mutations = "0 2 1\n"
309309

310310
/*** An example of a tree sequence with multiple roots. ***/
311311
/*
312-
0.90┊ ┊ 11 ┊ ┊
313-
┊ ┊ ┏┻┓ ┊ ┊
314-
0.80┊ 10┃ ┃ ┊ ┊
315-
┏┻┓┃ ┃ ┊ ┊
316-
0.40┊ ┃ ┃ 9 ┃ ┃ 9 ┊ 9 ┊
317-
┃ ┃ ┏━┻┓ ┃ ┃ ┏━┻━┓ ┊ ┏━┻━━┓ ┊
318-
0.30┊ ┃ ┃ ┃ ┃ ┃ 8 ┊ ┃ 8 ┊
319-
┃ ┃ ┃ ┃ ┃ ┏┻┓ ┊ ┃ ┏┻┓ ┊
320-
0.20┊ ┃ ┃ ┃ 7 ┃ ┃ ┃ 7 ┊ 7 ┃ ┃ ┊
321-
┃ ┃ ┃ ┏┻┓ ┊ ┃ ┃ ┃ ┃ ┏┻┓ ┊ ┏┻━┓ ┃ ┃ ┊
322-
0.10┊ ┃ ┃ ┃ ┃ ┃ ┊ ┃ ┃ ┃ ┃ ┃ ┃ ┊ 6 ┃ ┃ ┃ ┊
323-
┊ ┃ ┃ ┃ ┃ ┃ ┊ ┃ ┃ ┃ ┃ ┃ ┃ ┊ ┏┻┓ ┃ ┃ ┊
324-
0.00┊ 0 1 2 3 4 5 ┊ 0 5 1 2 3 4 ┊ 0 3 4 1 2 5 ┊
325-
0.00 4.00 8.00 10.00
312+
0.90┊ ┊ 11 ┊ ┊
313+
┊ ┊ ┏┻┓ ┊ ┊
314+
0.80┊ 10 ┃ ┃ ┊ ┊
315+
┏┻┓ ┃ ┃ ┊ ┊
316+
0.40┊ 9 ┃ ┃ 9 ┃ ┃ ┊ 9 ┊
317+
┏━┻┓ ┃ ┃ ┏━┻━┓ ┃ ┃ ┊ ┏━┻━━┓ ┊
318+
0.30┊ ┃ ┃ ┃ ┃ ┊ ┃ 8 ┃ ┃ ┊ ┃ 8 ┊
319+
┃ ┃ ┃ ┃ ┊ ┃ ┏┻┓ ┃ ┃ ┊ ┃ ┏┻┓ ┊
320+
0.20┊ ┃ 7 ┃ ┃ 7 ┃ ┃ ┃ ┊ 7 ┃ ┃ ┊
321+
┃ ┏┻┓ ┃ ┃┏┻┓ ┃ ┃ ┃ ┃ ┊ ┏━┻┓ ┃ ┃ ┊
322+
0.10┊ ┃ ┃ ┃ ┃ ┃ ┊ ┃ ┃ ┃ ┃ ┃ ┃ ┊ ┃ 6 ┃ ┃ ┊
323+
┃ ┃ ┃ ┃ ┃ ┊ ┃ ┃ ┃ ┃ ┃ ┃ ┊ ┏┻┓ ┃ ┃ ┊
324+
0.00┊ 5 2 3 4 0 1 ┊ 3 4 1 2 0 54 0 3 1 2 5 ┊
325+
0 4 8 10
326326
*/
327327
const char *multiroot_ex_nodes = "1 0.0 0 -1\n"
328328
"1 0.0 0 -1\n"

0 commit comments

Comments
 (0)