tests/test_tree.c

Thu, 15 Feb 2024 21:54:43 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 15 Feb 2024 21:54:43 +0100
changeset 826
21840975d541
parent 816
425234b05dff
child 833
5c926801f052
permissions
-rw-r--r--

add cx_tree_search() - relates to #165

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    29 #include "cx/tree.h"
    31 #include "cx/test.h"
    33 typedef struct tree_node {
    34     struct tree_node *parent;
    35     struct tree_node *next;
    36     struct tree_node *prev;
    37     struct tree_node *children;
    38     int data;
    39 } tree_node;
    41 #define tree_node_layout \
    42     offsetof(tree_node, parent), offsetof(tree_node, children), \
    43     offsetof(tree_node, prev), offsetof(tree_node, next)
    45 #define tree_child_list offsetof(tree_node, children),offsetof(tree_node, next)
    47 CX_TEST(test_tree_link_new_child) {
    48     tree_node parent = {0};
    49     tree_node child = {0};
    51     CX_TEST_DO {
    52         cx_tree_link(&parent, &child, tree_node_layout);
    53         CX_TEST_ASSERT(parent.next == NULL);
    54         CX_TEST_ASSERT(parent.prev == NULL);
    55         CX_TEST_ASSERT(parent.parent == NULL);
    56         CX_TEST_ASSERT(parent.children == &child);
    57         CX_TEST_ASSERT(child.parent == &parent);
    58         CX_TEST_ASSERT(child.next == NULL);
    59         CX_TEST_ASSERT(child.prev == NULL);
    60         CX_TEST_ASSERT(child.children == NULL);
    61     }
    62 }
    64 CX_TEST(test_tree_link_add_child) {
    65     tree_node parent = {0};
    66     tree_node child1 = {0};
    67     tree_node child2 = {0};
    68     tree_node child3 = {0};
    70     CX_TEST_DO {
    71         cx_tree_link(&parent, &child1, tree_node_layout);
    72         cx_tree_link(&parent, &child2, tree_node_layout);
    73         cx_tree_link(&parent, &child3, tree_node_layout);
    74         CX_TEST_ASSERT(parent.next == NULL);
    75         CX_TEST_ASSERT(parent.prev == NULL);
    76         CX_TEST_ASSERT(parent.parent == NULL);
    77         CX_TEST_ASSERT(parent.children == &child3);
    79         CX_TEST_ASSERT(child1.parent == &parent);
    80         CX_TEST_ASSERT(child2.parent == &parent);
    81         CX_TEST_ASSERT(child3.parent == &parent);
    82         CX_TEST_ASSERT(child1.children == NULL);
    83         CX_TEST_ASSERT(child2.children == NULL);
    84         CX_TEST_ASSERT(child3.children == NULL);
    86         CX_TEST_ASSERT(child3.prev == NULL);
    87         CX_TEST_ASSERT(child3.next == &child2);
    88         CX_TEST_ASSERT(child2.prev == &child3);
    89         CX_TEST_ASSERT(child2.next == &child1);
    90         CX_TEST_ASSERT(child1.prev == &child2);
    91         CX_TEST_ASSERT(child1.next == NULL);
    92     }
    93 }
    95 CX_TEST(test_tree_link_move_to_other_parent) {
    96     tree_node parent = {0};
    97     tree_node child1 = {0};
    98     tree_node child2 = {0};
    99     tree_node child3 = {0};
   100     cx_tree_link(&parent, &child1, tree_node_layout);
   101     cx_tree_link(&parent, &child2, tree_node_layout);
   102     cx_tree_link(&parent, &child3, tree_node_layout);
   104     CX_TEST_DO {
   105         cx_tree_link(&child3, &child2, tree_node_layout);
   107         CX_TEST_ASSERT(parent.next == NULL);
   108         CX_TEST_ASSERT(parent.prev == NULL);
   109         CX_TEST_ASSERT(parent.parent == NULL);
   110         CX_TEST_ASSERT(parent.children == &child3);
   112         CX_TEST_ASSERT(child1.parent == &parent);
   113         CX_TEST_ASSERT(child2.parent == &child3);
   114         CX_TEST_ASSERT(child3.parent == &parent);
   115         CX_TEST_ASSERT(child1.children == NULL);
   116         CX_TEST_ASSERT(child2.children == NULL);
   117         CX_TEST_ASSERT(child3.children == &child2);
   119         CX_TEST_ASSERT(child3.prev == NULL);
   120         CX_TEST_ASSERT(child3.next == &child1);
   121         CX_TEST_ASSERT(child1.prev == &child3);
   122         CX_TEST_ASSERT(child1.next == NULL);
   124         CX_TEST_ASSERT(child2.prev == NULL);
   125         CX_TEST_ASSERT(child2.next == NULL);
   126     }
   127 }
   129 CX_TEST(test_tree_unlink) {
   130     tree_node parent = {0};
   131     tree_node child1 = {0};
   132     tree_node child2 = {0};
   133     tree_node child3 = {0};
   134     cx_tree_link(&parent, &child1, tree_node_layout);
   135     cx_tree_link(&parent, &child3, tree_node_layout);
   136     cx_tree_link(&child3, &child2, tree_node_layout);
   138     CX_TEST_DO {
   139         cx_tree_unlink(&child3, tree_node_layout);
   141         CX_TEST_ASSERT(parent.next == NULL);
   142         CX_TEST_ASSERT(parent.prev == NULL);
   143         CX_TEST_ASSERT(parent.parent == NULL);
   144         CX_TEST_ASSERT(parent.children == &child1);
   146         CX_TEST_ASSERT(child1.parent == &parent);
   147         CX_TEST_ASSERT(child1.children == NULL);
   148         CX_TEST_ASSERT(child1.prev == NULL);
   149         CX_TEST_ASSERT(child1.next == NULL);
   151         // child 3 is unlinked
   152         CX_TEST_ASSERT(child3.parent == NULL);
   153         CX_TEST_ASSERT(child3.prev == NULL);
   154         CX_TEST_ASSERT(child3.next == NULL);
   156         // child 2 is still child of the unlinked child 3
   157         CX_TEST_ASSERT(child3.children == &child2);
   158         CX_TEST_ASSERT(child2.parent == &child3);
   159         CX_TEST_ASSERT(child2.children == NULL);
   160         CX_TEST_ASSERT(child2.prev == NULL);
   161         CX_TEST_ASSERT(child2.next == NULL);
   162     }
   163 }
   165 static int test_tree_search_function(void const *n, void const *d) {
   166     tree_node const *node = n;
   167     int data = *((int const*)d);
   169     if (data < node->data) return -1;
   170     else if (data == node->data) return 0;
   171     else return data - node->data;
   172 }
   174 CX_TEST(test_tree_search) {
   175     tree_node root = {0};
   176     tree_node a = {0};
   177     tree_node b = {0};
   178     tree_node c = {0};
   179     tree_node aa = {0};
   180     tree_node ab = {0};
   181     tree_node ba = {0};
   182     tree_node ca = {0};
   183     tree_node cb = {0};
   184     tree_node cc = {0};
   185     tree_node cba = {0};
   187     int testdata[] = {0, 10, 14, 18, 20, 25, 30, 32, 34, 36, 40};
   188     tree_node* testnodes[] = {&root, &a, &aa, &ab, &b, &ba, &c, &ca, &cb, &cba, &cc};
   190     for (unsigned i = 0 ; i <= 10 ; i++) {
   191         testnodes[i]->data = testdata[i];
   192     }
   194     cx_tree_link(&root, &a, tree_node_layout);
   195     cx_tree_link(&root, &b, tree_node_layout);
   196     cx_tree_link(&root, &c, tree_node_layout);
   198     cx_tree_link(&a, &aa, tree_node_layout);
   199     cx_tree_link(&a, &ab, tree_node_layout);
   201     cx_tree_link(&b, &ba, tree_node_layout);
   203     cx_tree_link(&c, &ca, tree_node_layout);
   204     cx_tree_link(&c, &cb, tree_node_layout);
   205     cx_tree_link(&c, &cc, tree_node_layout);
   207     cx_tree_link(&cb, &cba, tree_node_layout);
   209     int s;
   210     int r;
   211     tree_node *n;
   212     CX_TEST_DO {
   213         for (unsigned i = 0 ; i <= 10 ; i++) {
   214             s = testdata[i];
   215             r = cx_tree_search(&root, &s, test_tree_search_function,
   216                                (void **) &n, tree_child_list);
   217             CX_TEST_ASSERT(r == 0);
   218             CX_TEST_ASSERT(n == testnodes[i]);
   219         }
   221         s = -5;
   222         r = cx_tree_search(&root, &s, test_tree_search_function,
   223                            (void **) &n, tree_child_list);
   224         CX_TEST_ASSERT(r < 0);
   225         CX_TEST_ASSERT(n == NULL);
   227         s = 26;
   228         r = cx_tree_search(&root, &s, test_tree_search_function,
   229                            (void **) &n, tree_child_list);
   230         CX_TEST_ASSERT(r > 0);
   231         CX_TEST_ASSERT(n == &ba);
   233         s = 35;
   234         r = cx_tree_search(&root, &s, test_tree_search_function,
   235                            (void **) &n, tree_child_list);
   236         CX_TEST_ASSERT(r > 0);
   237         CX_TEST_ASSERT(n == &cb);
   239         s = 38;
   240         r = cx_tree_search(&root, &s, test_tree_search_function,
   241                            (void **) &n, tree_child_list);
   242         CX_TEST_ASSERT(r > 0);
   243         CX_TEST_ASSERT(n == &cba);
   245         s = 42;
   246         r = cx_tree_search(&root, &s, test_tree_search_function,
   247                            (void **) &n, tree_child_list);
   248         CX_TEST_ASSERT(r > 0);
   249         CX_TEST_ASSERT(n == &cc);
   250     }
   251 }
   253 CxTestSuite *cx_test_suite_tree_low_level(void) {
   254     CxTestSuite *suite = cx_test_suite_new("tree (low level)");
   256     cx_test_register(suite, test_tree_link_new_child);
   257     cx_test_register(suite, test_tree_link_add_child);
   258     cx_test_register(suite, test_tree_link_move_to_other_parent);
   259     cx_test_register(suite, test_tree_unlink);
   260     cx_test_register(suite, test_tree_search);
   262     return suite;
   263 }

mercurial