Cap the depth of a right-leaning tree too

Mutation testing found it: changing the right child's `depth + 1` to
`depth + 0` in the depth-first recursion survived the entire suite. The
depth cap was only ever tested against a chain that leans left, so
nothing said whether the right-hand descent counted at all -- a tree
that goes right for a million nodes would have recursed until the
process died, which is precisely what AKSL_TREE_MAX_DEPTH exists to
prevent.

The right-leaning chain is now tested in all three depth-first orders
and breadth-first, which carries its depth on the queue entry instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 08:09:04 -04:00
parent 3ad3994762
commit cc5e7899bb

View File

@@ -413,6 +413,40 @@ static int test_tree_deeper_than_the_cap_is_out_of_bounds(void)
AKSL_CHECK_OK(aksl_tree_iterate(&chain[0], &record_visit, NULL, NULL, AKSL_CHECK_OK(aksl_tree_iterate(&chain[0], &record_visit, NULL, NULL,
AKSL_TREE_SEARCH_DFS_PREORDER, &log)); AKSL_TREE_SEARCH_DFS_PREORDER, &log));
AKSL_CHECK(log.count == AKSL_TREE_MAX_DEPTH); AKSL_CHECK(log.count == AKSL_TREE_MAX_DEPTH);
/*
* And again leaning right. The recursion counts depth separately for each
* child, so a chain that only ever goes left says nothing about whether the
* right-hand descent counts at all -- mutation testing found exactly that:
* changing the right child's `depth + 1` to `depth + 0` survived the whole
* suite, because nothing here had ever recursed right more than three deep.
*/
for ( i = 0; i < AKSL_TREE_MAX_DEPTH + 2; i++ ) {
AKSL_CHECK_OK(aksl_tree_node_init(&chain[i], NULL));
}
for ( i = 0; i < AKSL_TREE_MAX_DEPTH + 1; i++ ) {
chain[i].right = &chain[i + 1];
}
visitlog_init(&log);
AKSL_CHECK_STATUS(aksl_tree_iterate(&chain[0], &record_visit, NULL, NULL,
AKSL_TREE_SEARCH_DFS_PREORDER, &log),
AKERR_OUTOFBOUNDS);
/* Both orders that descend right, so in-order and post-order count too. */
visitlog_init(&log);
AKSL_CHECK_STATUS(aksl_tree_iterate(&chain[0], &record_visit, NULL, NULL,
AKSL_TREE_SEARCH_DFS_INORDER, &log),
AKERR_OUTOFBOUNDS);
visitlog_init(&log);
AKSL_CHECK_STATUS(aksl_tree_iterate(&chain[0], &record_visit, NULL, NULL,
AKSL_TREE_SEARCH_DFS_POSTORDER, &log),
AKERR_OUTOFBOUNDS);
/* And breadth-first, whose depth is carried on the queue entry instead. */
visitlog_init(&log);
AKSL_CHECK_STATUS(aksl_tree_iterate(&chain[0], &record_visit, NULL, NULL,
AKSL_TREE_SEARCH_BFS, &log),
AKERR_OUTOFBOUNDS);
return 0; return 0;
} }