/* * Depth-first tree search. * * Previously this test shared one TreeSearchParams across all three searches * without resetting it, so `steps` accumulated (7, then 14, then 21) and the * second assertion failed -- `tree` was a red test on every run. Each search * now gets its own params. * * Caveat worth knowing when reading the step counts below: the value is hidden * in tree[6], which is the last node visited in pre-, in- and post-order alike, * so "7 steps" holds for all three orders and does not actually distinguish * them -- nor does it prove that AKERR_ITERATOR_BREAK stopped anything (it does * not; see tests/test_tree_iterate_break.c and TODO.md 2.1.3). Visit-order * assertions that tell the three traversals apart are TODO.md section 1.8. */ #include "aksl_capture.h" #define MAX_LEAVES 7 #define HIDDEN_VALUE ((void *)17336) typedef struct TreeSearchParams { void *value; int steps; aksl_TreeNode *node; } TreeSearchParams; static akerr_ErrorContext AKERR_NOIGNORE *find_value(aksl_TreeNode *node, void *data) { TreeSearchParams *parms = NULL; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, node, AKERR_NULLPOINTER, "node"); FAIL_ZERO_RETURN(e, data, AKERR_NULLPOINTER, "data"); parms = (TreeSearchParams *)data; parms->steps += 1; if ( node->leaf == parms->value ) { parms->node = node; FAIL_RETURN(e, AKERR_ITERATOR_BREAK, "stop"); } SUCCEED_RETURN(e); } /* * Build the 3-level tree used by every case here, with the search value hidden * in the bottom-right leaf. * * LEFT RIGHT * TREE[0] * +--------^^---------+ * | | * TREE[1] TREE[2] * +---^^---+ +---^^---+ * | | | | *TREE[3] TREE[4] TREE[5] TREE[6] */ static void build_tree(aksl_TreeNode *tree, TreeSearchParams *parms) { memset((void *)tree, 0x00, sizeof(aksl_TreeNode) * MAX_LEAVES); tree[0].left = &tree[1]; tree[0].right = &tree[2]; tree[1].left = &tree[3]; tree[1].right = &tree[4]; tree[2].left = &tree[5]; tree[2].right = &tree[6]; tree[6].leaf = HIDDEN_VALUE; memset((void *)parms, 0x00, sizeof(TreeSearchParams)); parms->value = HIDDEN_VALUE; } static int search_finds_hidden_value(uint8_t searchmode) { aksl_TreeNode tree[MAX_LEAVES]; TreeSearchParams parms; build_tree(tree, &parms); AKSL_CHECK_OK(aksl_tree_iterate(&tree[0], &find_value, NULL, NULL, searchmode, &parms, NULL)); AKSL_CHECK(parms.node == &tree[6]); AKSL_CHECK(parms.steps == MAX_LEAVES); return 0; } static int test_dfs_preorder(void) { return search_finds_hidden_value(AKSL_TREE_SEARCH_DFS_PREORDER); } static int test_dfs_inorder(void) { return search_finds_hidden_value(AKSL_TREE_SEARCH_DFS_INORDER); } static int test_dfs_postorder(void) { return search_finds_hidden_value(AKSL_TREE_SEARCH_DFS_POSTORDER); } int main(void) { int failures = 0; akerr_init(); AKSL_RUN(failures, test_dfs_preorder); AKSL_RUN(failures, test_dfs_inorder); AKSL_RUN(failures, test_dfs_postorder); AKSL_REPORT(failures); }