| 1371 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
1399 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| 1372 } |
1400 } |
| 1373 cx_testing_allocator_destroy(&talloc); |
1401 cx_testing_allocator_destroy(&talloc); |
| 1374 } |
1402 } |
| 1375 |
1403 |
| |
1404 CX_TEST(test_tree_high_create_root) { |
| |
1405 CxTestingAllocator talloc; |
| |
1406 cx_testing_allocator_init(&talloc); |
| |
1407 CX_TEST_DO { |
| |
1408 CxTree *tree = cxTreeCreate( |
| |
1409 &talloc.base, |
| |
1410 sizeof(tree_node_file), |
| |
1411 CX_STORE_POINTERS, |
| |
1412 NULL, -1, |
| |
1413 cx_tree_node_layout(tree_node_file) |
| |
1414 ); |
| |
1415 |
| |
1416 CX_TEST_ASSERT(tree->root == NULL); |
| |
1417 // create root without data |
| |
1418 tree_node_file *root = cxTreeCreateRoot(tree); |
| |
1419 CX_TEST_ASSERT(root != NULL); |
| |
1420 CX_TEST_ASSERT(root == tree->root); |
| |
1421 // re-create same root (does nothing) |
| |
1422 tree_node_file *root2 = cxTreeCreateRoot(tree); |
| |
1423 CX_TEST_ASSERT(root2 == root); |
| |
1424 |
| |
1425 // next test |
| |
1426 cxTreeClear(tree); |
| |
1427 |
| |
1428 // try to create with data, but loc_data is not known |
| |
1429 root = cxTreeCreateRootData(tree, "/"); |
| |
1430 CX_TEST_ASSERT(root == NULL); |
| |
1431 |
| |
1432 // set the loc_data |
| |
1433 tree->loc_data = offsetof(tree_node_file, path); |
| |
1434 root = cxTreeCreateRootData(tree, "/"); |
| |
1435 CX_TEST_ASSERT(root != NULL); |
| |
1436 CX_TEST_ASSERT(strcmp(root->path, "/") == 0); |
| |
1437 |
| |
1438 cxTreeFree(tree); |
| |
1439 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| |
1440 } |
| |
1441 } |
| |
1442 |
| |
1443 CX_TEST(test_tree_high_set_root) { |
| |
1444 CxTestingAllocator talloc; |
| |
1445 cx_testing_allocator_init(&talloc); |
| |
1446 CX_TEST_DO { |
| |
1447 CxTree *tree = cxTreeCreate( |
| |
1448 &talloc.base, |
| |
1449 sizeof(tree_node_file), |
| |
1450 CX_STORE_POINTERS, |
| |
1451 NULL, -1, |
| |
1452 cx_tree_node_layout(tree_node_file) |
| |
1453 ); |
| |
1454 |
| |
1455 CX_TEST_ASSERT(tree->root == NULL); |
| |
1456 |
| |
1457 tree_node_file *root = cxTreeCreateRoot(tree); |
| |
1458 CX_TEST_ASSERT(root != NULL); |
| |
1459 CX_TEST_ASSERT(root == tree->root); |
| |
1460 |
| |
1461 // create a different root externally |
| |
1462 tree_node_file *root2 = cxZalloc(&talloc.base, sizeof(tree_node_file)); |
| |
1463 |
| |
1464 // replace the root |
| |
1465 tree_node_file *old = cxTreeSetRoot(tree, root2); |
| |
1466 CX_TEST_ASSERT(old == root); |
| |
1467 |
| |
1468 // free the tree, check that there is memory leaking |
| |
1469 cxTreeFree(tree); |
| |
1470 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); |
| |
1471 |
| |
1472 // free the old root, check that memory is fine |
| |
1473 cxFree(&talloc.base, old); |
| |
1474 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| |
1475 } |
| |
1476 } |
| |
1477 |
| 1376 CX_TEST(test_tree_high_tree_depth) { |
1478 CX_TEST(test_tree_high_tree_depth) { |
| 1377 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
1479 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
| 1378 cx_tree_add(&root, &child1, tree_node_layout); |
1480 cx_tree_add(&root, &child1, tree_node_layout); |
| 1379 cx_tree_add(&root, &child2, tree_node_layout); |
1481 cx_tree_add(&root, &child2, tree_node_layout); |
| 1380 cx_tree_add(&child1, &child3, tree_node_layout); |
1482 cx_tree_add(&child1, &child3, tree_node_layout); |
| 1614 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, alloc, true); |
1716 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, alloc, true); |
| 1615 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, alloc, false); |
1717 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, alloc, false); |
| 1616 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
1718 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| 1617 } |
1719 } |
| 1618 cx_testing_allocator_destroy(&talloc); |
1720 cx_testing_allocator_destroy(&talloc); |
| |
1721 } |
| |
1722 |
| |
1723 CX_TEST(test_tree_high_add_find_without_loc_data) { |
| |
1724 CxTestingAllocator talloc; |
| |
1725 cx_testing_allocator_init(&talloc); |
| |
1726 CxAllocator *alloc = &talloc.base; |
| |
1727 CX_TEST_DO { |
| |
1728 CxTree *tree = cxTreeCreate(alloc, |
| |
1729 sizeof(tree_node_file), |
| |
1730 CX_STORE_POINTERS, |
| |
1731 NULL, offsetof(tree_node_file, path), |
| |
1732 cx_tree_node_layout(tree_node_file) |
| |
1733 ); |
| |
1734 cxSetCompareFunc(tree, strcmp); |
| |
1735 tree_node_file *root = cxTreeCreateRootData(tree, "/"); |
| |
1736 tree_node_file *home = cxTreeAddData(tree, root, "/home/"); |
| |
1737 tree_node_file *foo = cxTreeAddData(tree, home, "/home/foo/"); |
| |
1738 cxTreeAddData(tree, foo, "/home/foo/bar/"); |
| |
1739 tree_node_file *usr = cxTreeAddData(tree, root, "/usr/"); |
| |
1740 cxTreeAddData(tree, usr, "/usr/lib/"); |
| |
1741 |
| |
1742 void *found = cxTreeFind(tree, "/home/foo/", true); |
| |
1743 CX_TEST_ASSERT(found == foo); |
| |
1744 |
| |
1745 // now remove the loc_data |
| |
1746 tree->loc_data = -1; |
| |
1747 found = cxTreeFind(tree, "/home/foo/", true); |
| |
1748 CX_TEST_ASSERT(found == NULL); |
| |
1749 |
| |
1750 CX_TEST_ASSERT(NULL == cxTreeAddData(tree, root, "/usr/local/")); |
| |
1751 |
| |
1752 cxTreeFree(tree); |
| |
1753 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| |
1754 } |
| |
1755 cx_testing_allocator_destroy(&talloc); |
| |
1756 } |
| |
1757 |
| |
1758 CX_TEST(test_tree_high_find_max_depth) { |
| |
1759 CxTree *tree = cxTreeCreate(NULL, |
| |
1760 sizeof(tree_node_file), |
| |
1761 CX_STORE_POINTERS, |
| |
1762 NULL, offsetof(tree_node_file, path), |
| |
1763 cx_tree_node_layout(tree_node_file) |
| |
1764 ); |
| |
1765 cxSetCompareFunc(tree, strcmp); |
| |
1766 tree_node_file *root = cxTreeCreateRootData(tree, "/"); |
| |
1767 tree_node_file *home = cxTreeAddData(tree, root, "/home/"); |
| |
1768 tree_node_file *foo = cxTreeAddData(tree, home, "/home/foo/"); |
| |
1769 tree_node_file *bar = cxTreeAddData(tree, foo, "/home/foo/bar/"); |
| |
1770 tree_node_file *usr = cxTreeAddData(tree, root, "/usr/"); |
| |
1771 cxTreeAddData(tree, usr, "/usr/lib/"); |
| |
1772 CX_TEST_DO { |
| |
1773 CX_TEST_ASSERT(bar == cxTreeFindInSubtree(tree, "/home/foo/bar/", tree->root, 4, true)); |
| |
1774 CX_TEST_ASSERT(NULL == cxTreeFindInSubtree(tree, "/home/foo/bar/", tree->root, 3, true)); |
| |
1775 CX_TEST_ASSERT(bar == cxTreeFindInSubtree(tree, "/home/foo/bar/", home, 3, true)); |
| |
1776 CX_TEST_ASSERT(NULL == cxTreeFindInSubtree(tree, "/home/foo/bar/", home, 2, true)); |
| |
1777 } |
| |
1778 cxTreeFree(tree); |
| |
1779 } |
| |
1780 |
| |
1781 CX_TEST(test_tree_high_find_fast) { |
| |
1782 CxTree *tree = cxTreeCreate(NULL, |
| |
1783 sizeof(tree_node_file), |
| |
1784 CX_STORE_POINTERS, |
| |
1785 NULL, offsetof(tree_node_file, path), |
| |
1786 cx_tree_node_layout(tree_node_file) |
| |
1787 ); |
| |
1788 cxSetCompareFunc(tree, strcmp); |
| |
1789 tree_node_file *root = cxTreeCreateRootData(tree, "/"); |
| |
1790 tree_node_file *home = cxTreeAddData(tree, root, "/home/"); |
| |
1791 tree_node_file *foo = cxTreeAddData(tree, home, "/home/foo/"); |
| |
1792 tree_node_file *bar = cxTreeAddData(tree, foo, "/home/foo/bar/"); |
| |
1793 tree_node_file *baz = cxTreeAddData(tree, home, "/home/baz/"); |
| |
1794 tree_node_file *usr = cxTreeAddData(tree, root, "/usr/"); |
| |
1795 tree_node_file *lib = cxTreeAddData(tree, usr, "/usr/lib/"); |
| |
1796 CX_TEST_DO { |
| |
1797 // test that loc_data not needed for FindFast! |
| |
1798 tree->loc_data = -1; |
| |
1799 |
| |
1800 // find from root |
| |
1801 CX_TEST_ASSERT(root == cxTreeFindFast(tree, "/", |
| |
1802 tree_node_file_search_func)); |
| |
1803 CX_TEST_ASSERT(home == cxTreeFindFast(tree, "/home/", |
| |
1804 tree_node_file_search_func)); |
| |
1805 CX_TEST_ASSERT(foo == cxTreeFindFast(tree, "/home/foo/", |
| |
1806 tree_node_file_search_func)); |
| |
1807 CX_TEST_ASSERT(bar == cxTreeFindFast(tree, "/home/foo/bar/", |
| |
1808 tree_node_file_search_func)); |
| |
1809 CX_TEST_ASSERT(usr == cxTreeFindFast(tree, "/usr/", |
| |
1810 tree_node_file_search_func)); |
| |
1811 CX_TEST_ASSERT(lib == cxTreeFindFast(tree, "/usr/lib/", |
| |
1812 tree_node_file_search_func)); |
| |
1813 |
| |
1814 // find from correct subtree |
| |
1815 CX_TEST_ASSERT(foo == cxTreeFindFastInSubtree(tree, "/home/foo/", |
| |
1816 tree_node_file_search_func, home, 0)); |
| |
1817 CX_TEST_ASSERT(bar == cxTreeFindFastInSubtree(tree, "/home/foo/bar/", |
| |
1818 tree_node_file_search_func, home, 0)); |
| |
1819 CX_TEST_ASSERT(lib == cxTreeFindFastInSubtree(tree, "/usr/lib/", |
| |
1820 tree_node_file_search_func, usr, 0)); |
| |
1821 |
| |
1822 // find in wrong subtree |
| |
1823 CX_TEST_ASSERT(NULL == cxTreeFindFastInSubtree(tree, "/home/foo/", |
| |
1824 tree_node_file_search_func, usr, 0)); |
| |
1825 CX_TEST_ASSERT(NULL == cxTreeFindFastInSubtree(tree, "/home/foo/bar/", |
| |
1826 tree_node_file_search_func, baz, 0)); |
| |
1827 CX_TEST_ASSERT(NULL == cxTreeFindFastInSubtree(tree, "/usr/lib/", |
| |
1828 tree_node_file_search_func, home, 0)); |
| |
1829 |
| |
1830 // some tests with max depth |
| |
1831 // ------------------------- |
| |
1832 CX_TEST_ASSERT(bar == cxTreeFindFastInSubtree(tree, "/home/foo/bar/", tree_node_file_search_func, tree->root, 4)); |
| |
1833 CX_TEST_ASSERT(NULL == cxTreeFindFastInSubtree(tree, "/home/foo/bar/", tree_node_file_search_func, tree->root, 3)); |
| |
1834 CX_TEST_ASSERT(bar == cxTreeFindFastInSubtree(tree, "/home/foo/bar/", tree_node_file_search_func, home, 3)); |
| |
1835 CX_TEST_ASSERT(NULL == cxTreeFindFastInSubtree(tree, "/home/foo/bar/", tree_node_file_search_func, home, 2)); |
| |
1836 } |
| |
1837 cxTreeFree(tree); |
| 1619 } |
1838 } |
| 1620 |
1839 |
| 1621 CX_TEST(test_tree_high_remove_or_destroy_root) { |
1840 CX_TEST(test_tree_high_remove_or_destroy_root) { |
| 1622 CxTestingAllocator talloc; |
1841 CxTestingAllocator talloc; |
| 1623 cx_testing_allocator_init(&talloc); |
1842 cx_testing_allocator_init(&talloc); |
| 1726 actual_order[iter.counter-1] = p->path; |
1945 actual_order[iter.counter-1] = p->path; |
| 1727 } |
1946 } |
| 1728 CX_TEST_ASSERT(iter.counter == 9); |
1947 CX_TEST_ASSERT(iter.counter == 9); |
| 1729 for (unsigned i = 0; i < 9; i++) { |
1948 for (unsigned i = 0; i < 9; i++) { |
| 1730 CX_TEST_ASSERT(strcmp(expected_order[i], actual_order[i]) == 0); |
1949 CX_TEST_ASSERT(strcmp(expected_order[i], actual_order[i]) == 0); |
| |
1950 } |
| |
1951 } |
| |
1952 cxTreeFree(tree); |
| |
1953 } |
| |
1954 |
| |
1955 CX_TEST(test_tree_high_iterator_large_depth) { |
| |
1956 CxTree *tree = cxTreeCreate(NULL, |
| |
1957 sizeof(tree_node), |
| |
1958 sizeof(int), |
| |
1959 NULL, offsetof(tree_node, data), |
| |
1960 tree_node_layout |
| |
1961 ); |
| |
1962 int c = 0; |
| |
1963 tree_node *root = cxTreeCreateRootData(tree, &c); |
| |
1964 unsigned depths[6] = {10, 20, 15, 30, 25, 5}; |
| |
1965 for (unsigned b = 0 ; b < 3 ; b++) { |
| |
1966 c++; |
| |
1967 tree_node *branch = cxTreeAddData(tree, root, &c); |
| |
1968 tree_node *p = branch; |
| |
1969 for (unsigned d = 0; d < depths[b*2+0] ; d++) { |
| |
1970 c++; |
| |
1971 p = cxTreeAddData(tree, p, &c); |
| |
1972 } |
| |
1973 p = branch; |
| |
1974 for (unsigned d = 0; d < depths[b*2+1] ; d++) { |
| |
1975 c++; |
| |
1976 p = cxTreeAddData(tree, p, &c); |
| |
1977 } |
| |
1978 } |
| |
1979 CX_TEST_DO { |
| |
1980 CX_TEST_ASSERT(cxTreeSize(tree) == 109); |
| |
1981 CX_TEST_ASSERT(cxTreeSubtreeSize(tree, root) == 109); |
| |
1982 CX_TEST_ASSERT(cxTreeSubtreeSize(tree, root->children) == 1+depths[0]+depths[1]); |
| |
1983 CX_TEST_ASSERT(cxTreeSubtreeSize(tree, root->children->next) == 1+depths[2]+depths[3]); |
| |
1984 CX_TEST_ASSERT(cxTreeSubtreeSize(tree, root->children->next->next) == 1+depths[4]+depths[5]); |
| |
1985 CxTreeIterator iter = cxTreeIterate(tree, false); |
| |
1986 cx_foreach(tree_node*, n, iter) { |
| |
1987 CX_TEST_ASSERT((size_t)n->data == iter.counter - 1); |
| 1731 } |
1988 } |
| 1732 } |
1989 } |
| 1733 cxTreeFree(tree); |
1990 cxTreeFree(tree); |
| 1734 } |
1991 } |
| 1735 |
1992 |
| 1810 |
2068 |
| 1811 CxTestSuite *cx_test_suite_tree_high_level(void) { |
2069 CxTestSuite *cx_test_suite_tree_high_level(void) { |
| 1812 CxTestSuite *suite = cx_test_suite_new("tree (high level)"); |
2070 CxTestSuite *suite = cx_test_suite_new("tree (high level)"); |
| 1813 |
2071 |
| 1814 cx_test_register(suite, test_tree_high_create); |
2072 cx_test_register(suite, test_tree_high_create); |
| |
2073 cx_test_register(suite, test_tree_high_create_root); |
| |
2074 cx_test_register(suite, test_tree_high_set_root); |
| 1815 cx_test_register(suite, test_tree_high_tree_depth); |
2075 cx_test_register(suite, test_tree_high_tree_depth); |
| 1816 cx_test_register(suite, test_tree_high_set_parent); |
2076 cx_test_register(suite, test_tree_high_set_parent); |
| 1817 cx_test_register(suite, test_tree_high_add_find_remove_nodes); |
2077 cx_test_register(suite, test_tree_high_add_find_remove_nodes); |
| 1818 cx_test_register(suite, test_tree_high_add_find_destroy_nodes); |
2078 cx_test_register(suite, test_tree_high_add_find_destroy_nodes); |
| |
2079 cx_test_register(suite, test_tree_high_add_find_without_loc_data); |
| |
2080 cx_test_register(suite, test_tree_high_find_max_depth); |
| |
2081 cx_test_register(suite, test_tree_high_find_fast); |
| 1819 cx_test_register(suite, test_tree_high_remove_or_destroy_root); |
2082 cx_test_register(suite, test_tree_high_remove_or_destroy_root); |
| 1820 cx_test_register(suite, test_tree_high_simple_destructor); |
2083 cx_test_register(suite, test_tree_high_simple_destructor); |
| 1821 cx_test_register(suite, test_tree_high_iterator); |
2084 cx_test_register(suite, test_tree_high_iterator); |
| |
2085 cx_test_register(suite, test_tree_high_iterator_large_depth); |
| 1822 cx_test_register(suite, test_tree_high_visitor); |
2086 cx_test_register(suite, test_tree_high_visitor); |
| 1823 |
2087 |
| 1824 return suite; |
2088 return suite; |
| 1825 } |
2089 } |