END_TEST /* here we construct a tree in the following form : * 1 * / / / \ \ \ * 7 2 6 4 3 5 * numbers are chronological adding order. */ START_TEST(test_xtree_with_add_sibling) { xtree_t* tree = &mytree_empty; char* fake_addr = (char*)1; fail_unless(xtree_add_sibling(tree, NULL, fake_addr, XTREE_APPEND) != NULL, NULL); /* 1 */ ++fake_addr; fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND) != NULL, NULL); /* 2 */ fail_unless(xtree_add_sibling(tree, tree->root, fake_addr, XTREE_APPEND) == NULL, "add_sibling should return null when used with root node"); ++fake_addr; fail_unless(xtree_add_sibling(tree, tree->root->start, fake_addr, XTREE_APPEND) != NULL, NULL); /* 3 */ ++fake_addr; fail_unless(xtree_add_sibling(tree, tree->root->end, fake_addr, XTREE_PREPEND) != NULL, NULL); /* 4 */ ++fake_addr; fail_unless(xtree_add_sibling(tree, tree->root->end, fake_addr, XTREE_APPEND) != NULL, NULL); /* 5 */ ++fake_addr; fail_unless(xtree_add_sibling(tree, tree->root->start, fake_addr, XTREE_APPEND) != NULL, NULL); /* 6 */ ++fake_addr; fail_unless(xtree_add_sibling(tree, tree->root->start, fake_addr, XTREE_PREPEND) != NULL, NULL); /* 7 */ fail_unless(tree->root->data == (void*)1, "bad root node"); fail_unless(tree->root->start->data == (void*)7 && tree->root->start->next->data == (void*)2 && tree->root->start->next->next->data == (void*)6 && tree->root->start->next->next->next->data == (void*)4, "bad tree structure browsing forward"); fail_unless(tree->root->end->data == (void*)5 && tree->root->end->previous->data == (void*)3 && tree->root->end->previous->previous->data == (void*)4 && tree->root->end->previous->previous->previous->data == (void*)6, "bad tree structure browsing backward"); fail_unless(tree->root->start->previous == NULL && tree->root->end->next == NULL, "bad tree edges"); fail_unless(tree->root->start->start == NULL && /* 7 */ tree->root->start->next->start == NULL && /* 2 */ tree->root->start->next->next->start == NULL && /* 6 */ tree->root->end->start == NULL && /* 5 */ tree->root->end->previous->start == NULL && /* 3 */ tree->root->end->previous->previous->start == NULL, /* 4 */ "bad tree structure level 1 should not have children"); }
/* here we construct a tree in the following form : * 1 * / / \ \ * 6 2 3 5 * / \ * 7 4 * numbers are chronological adding order. */ static void init_by_addchild(void) { xtree_t* tree = &mytree_by_addchild; char* fake_addr = (char*)1; xtree_add_child(tree, NULL, fake_addr, XTREE_APPEND); ++fake_addr; xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND); ++fake_addr; xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND); ++fake_addr; xtree_add_child(tree, tree->root->start, fake_addr, XTREE_APPEND); ++fake_addr; xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND); ++fake_addr; xtree_add_child(tree, tree->root, fake_addr, XTREE_PREPEND); ++fake_addr; xtree_add_child(tree, tree->root->start->next, fake_addr, XTREE_PREPEND); }
END_TEST START_TEST(test_xtree_add_root_node_unmanaged) { xtree_t* tree = &mytree_empty; char* fake_addr = (char*)1; fail_unless(xtree_add_child(tree, NULL, fake_addr, XTREE_APPEND) != NULL, "unable to add root node"); fail_unless(tree->root != NULL, "root node has not been allocated"); fail_unless(tree->free == NULL, "bad free function in the tree"); fail_unless(tree->count == 1, "there should be at least one node and only one in node count"); fail_unless(xtree_depth_const(tree) == 1, "tree should have a depth of one (depth %d)", xtree_depth_const(tree)); fail_unless(tree->root->data == (void*)1, "node data is incorrect"); fail_unless(tree->root->parent == NULL, "root node has a parent"); fail_unless(tree->root->start == NULL && tree->root->end == NULL, "root node should not already have child in it"); fail_unless(tree->root->next == NULL && tree->root->previous == NULL, "root node have invalid siblings"); xtree_refresh_depth(tree); fail_unless(tree->depth == 1, "root node refreshed should have one depth (root level)"); fail_unless(tree->state == XTREE_STATE_DEPTHCACHED, "root node should now have its depth been cached"); ++fake_addr; fail_unless(xtree_add_child(tree, NULL, fake_addr, XTREE_APPEND) == NULL, "xtree_add_child with NULL parent and root node in tree should " "return a NULL pointer"); fail_unless(tree->root->data == (void*)1, "xtree_add_child generated an operation and should not in context"); fail_unless(tree->root->start == NULL, "xtree_add_child had added an invalid child"); fail_unless(tree->root->start == tree->root->end, "xtree_add_child invalidated root node child list"); fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND) != NULL, "unable to add child node to root node"); fail_unless(tree->count == 2, "bad tree node count"); fail_unless(xtree_depth_const(tree) == 2, "bad depth after root's first child"); fail_unless(tree->state != XTREE_STATE_DEPTHCACHED, "tree should not have already cached level count"); fail_unless(tree->root && tree->root->data == (void*)1 && tree->root->parent == NULL && tree->root->next == NULL && tree->root->previous == NULL, "root node has badly been modified"); fail_unless(!!tree->root->start, "root has no child, but should have one"); fail_unless(tree->root->start == tree->root->end, "root child list is inconsistent"); fail_unless(tree->root->start->data == (void*)2, "bad child data"); fail_unless(tree->root->start->parent == tree->root, "child parent does not point to root node"); fail_unless(!tree->root->start->start, "child should be unique for now"); fail_unless(tree->root->start->start == tree->root->start->end, "child children list is inconsistent"); fail_unless(!tree->root->start->next && !tree->root->start->previous, "child should not have siblings"); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND) != NULL, "unable to add second child"); fail_unless(tree->root->start != tree->root->end, "root should have more children"); fail_unless(tree->root->start->next == tree->root->end && tree->root->end->previous == tree->root->start && tree->root->end->next == NULL && tree->root->start->previous == NULL, "root children list is inconsistent"); fail_unless(tree->root->end->data == (void*)3, "root second child has bad data"); }
END_TEST /* here we construct a tree in the following form : * 1 * / / \ \ * 6 2 3 5 * / \ * 7 4 * numbers are chronological adding order. */ START_TEST(test_xtree_with_add_child) { xtree_t* tree = &mytree_empty; xtree_node_t* level1_2 = NULL; char* fake_addr = (char*)1; fail_unless(xtree_add_child(tree, NULL, fake_addr, XTREE_APPEND) != NULL, NULL); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND) != NULL, NULL); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND) != NULL, NULL); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root->start, fake_addr, XTREE_APPEND) != NULL, NULL); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_APPEND) != NULL, NULL); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root, fake_addr, XTREE_PREPEND) != NULL, NULL); ++fake_addr; fail_unless(xtree_add_child(tree, tree->root->start->next, fake_addr, XTREE_PREPEND) != NULL, NULL); fail_unless(tree->root->start->data == (void*)6 && tree->root->start->next->data == (void*)2 && tree->root->start->next->next->data == (void*)3 && tree->root->start->next->next->next->data == (void*)5, "bad tree for children level 1 browsing the tree forward"); fail_unless(tree->root->end->data == (void*)5 && tree->root->end->previous->data == (void*)3 && tree->root->end->previous->previous->data == (void*)2 && tree->root->end->previous->previous->previous->data == (void*)6, "bad tree for children level 1 browsing backward"); fail_unless(tree->root->start->previous == NULL && tree->root->end->next == NULL, "bad tree edges"); fail_unless(tree->root->start->start == NULL && /* 6 */ tree->root->start->next->start != NULL && /* 2 */ tree->root->start->next->end != NULL && /* 2 */ tree->root->start->next->start != /* 2 */ tree->root->start->next->end && /* 2 */ tree->root->start->next->next->start == NULL && /* 3 */ tree->root->start->next->next->next->start == NULL, /* 5 */ "bad tree structure for children of child list level 1"); level1_2 = tree->root->start->next; fail_unless(level1_2->start->data == (void*)7 && level1_2->start->start == NULL && level1_2->start->previous == NULL && level1_2->start->next == level1_2->end && level1_2->end->data == (void*)4 && level1_2->end->next == NULL && level1_2->end->start == NULL, "bad tree structure for children level 2"); }
/* here we construct a tree in the following form : * 1 * / / \ \ * 6 2 3 5 * / \ * 7 4 * numbers are chronological adding order. */ void addchild_walk_test() { xtree_t *my_tree = (xtree_t *)xmalloc(sizeof(xtree_t)); person_t *person = NULL; person_t *direct_parent_person = NULL; person_t *parent_of_delete_person = NULL; char buf[256]; xtree_node_t* node = NULL; xtree_node_t* direct_parent_node = NULL; xtree_node_t* parent_of_delete_node = NULL; uint32_t arg = 0; int i; /* init my_tree with free element function */ xtree_init(my_tree, xtree_free_node_func); for (i = 1; i < 8; i++) { person = (person_t *)xmalloc(sizeof(person_t)); person->id = i; person->age = i; snprintf(buf, 256, "name_%d", i); person->name = xstrdup(buf); if (1 == i) xtree_add_child(my_tree, NULL, person, XTREE_APPEND); else if (2 == i) xtree_add_child(my_tree, my_tree->root, person, XTREE_APPEND); else if (3 == i) xtree_add_child(my_tree, my_tree->root, person, XTREE_APPEND); else if (4 == i) /* my_tree->root is 1, then 1's ->start is 2 */ xtree_add_child(my_tree, my_tree->root->start, person, XTREE_APPEND); else if (5 == i) xtree_add_child(my_tree, my_tree->root, person, XTREE_APPEND); else if (6 == i) xtree_add_child(my_tree, my_tree->root, person, XTREE_PREPEND); else if (7 == i) /* my_tree->root is 1, then 1's ->start is 2 */ /* XTREE_PREPEND */ xtree_add_child(my_tree, my_tree->root->start->next, person, XTREE_PREPEND); } arg = 4; node = xtree_find(my_tree, find_compare_func, &arg); if (NULL != node) { person = (person_t *) node->data; puts("xtree_find success!, my info: "); printf("person->id = %lu\n", person->id); printf("person->age = %lu\n", person->age); printf("person->name = %s\n", person->name); /* print person's depth */ printf("person\'s depth = %lu\n", xtree_node_depth(node)); puts("my parent\'s info: "); direct_parent_node = xtree_get_parent(my_tree, node); direct_parent_person = (person_t *) direct_parent_node->data; printf("direct_parent_person->id = %lu\n", direct_parent_person->id); printf("direct_parent_person->age = %lu\n", direct_parent_person->age); printf("direct_parent_person->name = %s\n", direct_parent_person->name); /* print parent's depth */ printf("parent's depth = %lu\n", xtree_node_depth(direct_parent_person)); puts("try to delete the parent node (2):"); parent_of_delete_node = xtree_delete(my_tree, direct_parent_node); parent_of_delete_person = (person_t *)parent_of_delete_node->data; printf("parent_of_delete_person->id = %lu\n", parent_of_delete_person->id); printf("parent_of_delete_person->age = %lu\n", parent_of_delete_person->age); printf("parent_of_delete_person->name = %s\n", parent_of_delete_person->name); } puts("at last, free all nodes in the tree:"); /* to free element */ xtree_free(my_tree); /* to free my_tree itself memory */ xfree(my_tree); }