|      1 /* | 
        | 
|      2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | 
        | 
|      3  * | 
        | 
|      4  * Copyright 2021 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  */ | 
        | 
|     28  | 
        | 
|     29 #include "cx/linked_list.h" | 
        | 
|     30 #include "cx/utils.h" | 
        | 
|     31 #include "test_config.h" | 
        | 
|     32 #include "util_allocator.h" | 
        | 
|     33  | 
        | 
|     34 static int cmp_int_impl( | 
        | 
|     35         int const *l, | 
        | 
|     36         int const *r | 
        | 
|     37 ) { | 
        | 
|     38     int left = *l, right = *r; | 
        | 
|     39     return left == right ? 0 : (left < right ? -1 : 1); | 
        | 
|     40 } | 
        | 
|     41  | 
        | 
|     42 #define cmp_int ((CxListComparator) cmp_int_impl) | 
        | 
|     43  | 
        | 
|     44 struct node { | 
        | 
|     45     struct node *next; | 
        | 
|     46     struct node *prev; | 
        | 
|     47     int data; | 
        | 
|     48 }; | 
        | 
|     49  | 
        | 
|     50 #define nd(name) name = {0} | 
        | 
|     51  | 
        | 
|     52 const ptrdiff_t loc_prev = offsetof(struct node, prev); | 
        | 
|     53 const ptrdiff_t loc_next = offsetof(struct node, next); | 
        | 
|     54 const ptrdiff_t loc_data = offsetof(struct node, data); | 
        | 
|     55  | 
        | 
|     56 static struct node *create_nodes_test_data( | 
        | 
|     57         size_t n, | 
        | 
|     58         int const data[] | 
        | 
|     59 ) { | 
        | 
|     60     CU_ASSERT_NOT_EQUAL_FATAL(n, 0) | 
        | 
|     61     struct node *begin = calloc(1, sizeof(struct node)); | 
        | 
|     62     struct node *prev = begin; | 
        | 
|     63     if (data) begin->data = data[0]; | 
        | 
|     64     for (size_t i = 1; i < n; i++) { | 
        | 
|     65         struct node *node = calloc(1, sizeof(struct node)); | 
        | 
|     66         if (data) node->data = data[i]; | 
        | 
|     67         cx_linked_list_link(prev, node, loc_prev, loc_next); | 
        | 
|     68         prev = node; | 
        | 
|     69     } | 
        | 
|     70     return begin; | 
        | 
|     71 } | 
        | 
|     72  | 
        | 
|     73 static void destroy_nodes_test_data(struct node *begin) { | 
        | 
|     74     struct node *node = begin; | 
        | 
|     75     while (node) { | 
        | 
|     76         struct node *next = node->next; | 
        | 
|     77         free(node); | 
        | 
|     78         node = next; | 
        | 
|     79     } | 
        | 
|     80 } | 
        | 
|     81  | 
        | 
|     82 static int *create_ints_test_data(size_t len) { | 
        | 
|     83     int *data = malloc(sizeof(int) * len); | 
        | 
|     84     cx_for_n (i, len) data[i] = rand(); // NOLINT(cert-msc50-cpp) | 
        | 
|     85     return data; | 
        | 
|     86 } | 
        | 
|     87  | 
        | 
|     88 void test_linked_list_link_unlink(void) { | 
        | 
|     89  | 
        | 
|     90     struct node nd(a), nd(b), nd(c); | 
        | 
|     91  | 
        | 
|     92     cx_linked_list_link(&a, &b, loc_prev, loc_next); | 
        | 
|     93     CU_ASSERT_PTR_NULL(a.prev) | 
        | 
|     94     CU_ASSERT_PTR_EQUAL(a.next, &b) | 
        | 
|     95     CU_ASSERT_PTR_EQUAL(b.prev, &a) | 
        | 
|     96     CU_ASSERT_PTR_NULL(b.next) | 
        | 
|     97  | 
        | 
|     98     cx_linked_list_unlink(&a, &b, loc_prev, loc_next); | 
        | 
|     99     CU_ASSERT_PTR_NULL(a.prev) | 
        | 
|    100     CU_ASSERT_PTR_NULL(a.next) | 
        | 
|    101     CU_ASSERT_PTR_NULL(b.prev) | 
        | 
|    102     CU_ASSERT_PTR_NULL(b.next) | 
        | 
|    103  | 
        | 
|    104     cx_linked_list_link(&b, &c, loc_prev, loc_next); | 
        | 
|    105     cx_linked_list_link(&a, &b, loc_prev, loc_next); | 
        | 
|    106     cx_linked_list_unlink(&b, &c, loc_prev, loc_next); | 
        | 
|    107     CU_ASSERT_PTR_NULL(a.prev) | 
        | 
|    108     CU_ASSERT_PTR_EQUAL(a.next, &b) | 
        | 
|    109     CU_ASSERT_PTR_EQUAL(b.prev, &a) | 
        | 
|    110     CU_ASSERT_PTR_NULL(b.next) | 
        | 
|    111     CU_ASSERT_PTR_NULL(c.prev) | 
        | 
|    112     CU_ASSERT_PTR_NULL(c.next) | 
        | 
|    113 } | 
        | 
|    114  | 
        | 
|    115 void test_linked_list_at(void) { | 
        | 
|    116     struct node nd(a), nd(b), nd(c), nd(d); | 
        | 
|    117     cx_linked_list_link(&a, &b, loc_prev, loc_next); | 
        | 
|    118     cx_linked_list_link(&b, &c, loc_prev, loc_next); | 
        | 
|    119     cx_linked_list_link(&c, &d, loc_prev, loc_next); | 
        | 
|    120  | 
        | 
|    121     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 0), &a) | 
        | 
|    122     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 1), &b) | 
        | 
|    123     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 2), &c) | 
        | 
|    124     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 3), &d) | 
        | 
|    125     CU_ASSERT_PTR_NULL(cx_linked_list_at(&a, 0, loc_next, 4)) | 
        | 
|    126  | 
        | 
|    127     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_prev, 0), &a) | 
        | 
|    128     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 1), &b) | 
        | 
|    129     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 2), &c) | 
        | 
|    130     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 3), &d) | 
        | 
|    131     CU_ASSERT_PTR_NULL(cx_linked_list_at(&b, 1, loc_next, 4)) | 
        | 
|    132  | 
        | 
|    133     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 0), &a) | 
        | 
|    134     CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 1), &b) | 
        | 
|    135 } | 
        | 
|    136  | 
        | 
|    137 void test_linked_list_find(void) { | 
        | 
|    138     int data[] = {2, 4, 6, 8}; | 
        | 
|    139     void *list = create_nodes_test_data(4, data); | 
        | 
|    140     int s; | 
        | 
|    141  | 
        | 
|    142     s = 2; | 
        | 
|    143     CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, | 
        | 
|    144                                         false, cmp_int, &s), 0) | 
        | 
|    145     s = 4; | 
        | 
|    146     CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, | 
        | 
|    147                                         false, cmp_int, &s), 1) | 
        | 
|    148     s = 6; | 
        | 
|    149     CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, | 
        | 
|    150                                         false, cmp_int, &s), 2) | 
        | 
|    151     s = 8; | 
        | 
|    152     CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, | 
        | 
|    153                                         false, cmp_int, &s), 3) | 
        | 
|    154     s = 10; | 
        | 
|    155     CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, | 
        | 
|    156                                         false, cmp_int, &s), 4) | 
        | 
|    157     s = -2; | 
        | 
|    158     CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, | 
        | 
|    159                                         false, cmp_int, &s), 4) | 
        | 
|    160 } | 
        | 
|    161  | 
        | 
|    162 void test_linked_list_compare(void) { | 
        | 
|    163     int a[] = {2, 4, 6, 8}; | 
        | 
|    164     int b[] = {2, 4, 6}; | 
        | 
|    165     int c[] = {2, 4, 6, 9}; | 
        | 
|    166  | 
        | 
|    167     void *la = create_nodes_test_data(4, a); | 
        | 
|    168     void *lb = create_nodes_test_data(3, b); | 
        | 
|    169     void *lc = create_nodes_test_data(4, c); | 
        | 
|    170  | 
        | 
|    171     CU_ASSERT_TRUE(0 < cx_linked_list_compare(la, lb, loc_next, loc_data, | 
        | 
|    172                                               false, cmp_int) | 
        | 
|    173     ) | 
        | 
|    174     CU_ASSERT_TRUE(0 > cx_linked_list_compare(lb, la, loc_next, loc_data, | 
        | 
|    175                                               false, cmp_int) | 
        | 
|    176     ) | 
        | 
|    177     CU_ASSERT_TRUE(0 < cx_linked_list_compare(lc, la, loc_next, loc_data, | 
        | 
|    178                                               false, cmp_int) | 
        | 
|    179     ) | 
        | 
|    180     CU_ASSERT_TRUE(0 > cx_linked_list_compare(la, lc, loc_next, loc_data, | 
        | 
|    181                                               false, cmp_int) | 
        | 
|    182     ) | 
        | 
|    183     CU_ASSERT_TRUE(0 == cx_linked_list_compare(la, la, loc_next, loc_data, | 
        | 
|    184                                                false, cmp_int) | 
        | 
|    185     ) | 
        | 
|    186  | 
        | 
|    187     destroy_nodes_test_data(la); | 
        | 
|    188     destroy_nodes_test_data(lb); | 
        | 
|    189     destroy_nodes_test_data(lc); | 
        | 
|    190 } | 
        | 
|    191  | 
        | 
|    192 void test_linked_list_add(void) { | 
        | 
|    193     struct node nodes[4]; | 
        | 
|    194     void *begin, *end; | 
        | 
|    195  | 
        | 
|    196     // test with begin, end / prev, next | 
        | 
|    197     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    198     begin = end = NULL; | 
        | 
|    199  | 
        | 
|    200     cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); | 
        | 
|    201     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    202     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    203     CU_ASSERT_PTR_NULL(nodes[0].prev) | 
        | 
|    204     CU_ASSERT_PTR_NULL(nodes[0].next) | 
        | 
|    205  | 
        | 
|    206     cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); | 
        | 
|    207     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    208     CU_ASSERT_PTR_EQUAL(end, &nodes[1]) | 
        | 
|    209     CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) | 
        | 
|    210     CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) | 
        | 
|    211  | 
        | 
|    212     // test with begin only / prev, next | 
        | 
|    213     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    214     begin = end = NULL; | 
        | 
|    215  | 
        | 
|    216     cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]); | 
        | 
|    217     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    218     cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[1]); | 
        | 
|    219     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    220     CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) | 
        | 
|    221     CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) | 
        | 
|    222  | 
        | 
|    223     cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[2]); | 
        | 
|    224     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) | 
        | 
|    225     CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) | 
        | 
|    226  | 
        | 
|    227     // test with end only / prev, next | 
        | 
|    228     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    229     begin = end = NULL; | 
        | 
|    230  | 
        | 
|    231     cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[0]); | 
        | 
|    232     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    233     cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[1]); | 
        | 
|    234     CU_ASSERT_PTR_EQUAL(end, &nodes[1]) | 
        | 
|    235     CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) | 
        | 
|    236     CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) | 
        | 
|    237  | 
        | 
|    238     cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[2]); | 
        | 
|    239     CU_ASSERT_PTR_EQUAL(end, &nodes[2]) | 
        | 
|    240     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) | 
        | 
|    241     CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) | 
        | 
|    242  | 
        | 
|    243     // test with begin, end / next | 
        | 
|    244     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    245     begin = end = NULL; | 
        | 
|    246  | 
        | 
|    247     cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); | 
        | 
|    248     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    249     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    250     cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); | 
        | 
|    251     CU_ASSERT_PTR_EQUAL(end, &nodes[1]) | 
        | 
|    252     CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) | 
        | 
|    253     CU_ASSERT_PTR_NULL(nodes[1].prev) | 
        | 
|    254 } | 
        | 
|    255  | 
        | 
|    256 void test_linked_list_prepend(void) { | 
        | 
|    257     struct node nodes[4]; | 
        | 
|    258     void *begin, *end; | 
        | 
|    259  | 
        | 
|    260     // test with begin, end / prev, next | 
        | 
|    261     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    262     begin = end = NULL; | 
        | 
|    263  | 
        | 
|    264     cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); | 
        | 
|    265     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    266     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    267     CU_ASSERT_PTR_NULL(nodes[0].prev) | 
        | 
|    268     CU_ASSERT_PTR_NULL(nodes[0].next) | 
        | 
|    269  | 
        | 
|    270     cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); | 
        | 
|    271     CU_ASSERT_PTR_EQUAL(begin, &nodes[1]) | 
        | 
|    272     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    273     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) | 
        | 
|    274     CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) | 
        | 
|    275  | 
        | 
|    276     // test with begin only / prev, next | 
        | 
|    277     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    278     begin = end = NULL; | 
        | 
|    279  | 
        | 
|    280     cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[0]); | 
        | 
|    281     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    282     cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[1]); | 
        | 
|    283     CU_ASSERT_PTR_EQUAL(begin, &nodes[1]) | 
        | 
|    284     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) | 
        | 
|    285     CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) | 
        | 
|    286  | 
        | 
|    287     cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[2]); | 
        | 
|    288     CU_ASSERT_PTR_EQUAL(begin, &nodes[2]) | 
        | 
|    289     CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) | 
        | 
|    290     CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[2]) | 
        | 
|    291  | 
        | 
|    292     // test with end only / prev, next | 
        | 
|    293     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    294     begin = end = NULL; | 
        | 
|    295  | 
        | 
|    296     cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[0]); | 
        | 
|    297     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    298     cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[1]); | 
        | 
|    299     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    300     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) | 
        | 
|    301     CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) | 
        | 
|    302  | 
        | 
|    303     cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[2]); | 
        | 
|    304     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    305     CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) | 
        | 
|    306     CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[2]) | 
        | 
|    307  | 
        | 
|    308     // test with begin, end / next | 
        | 
|    309     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    310     begin = end = NULL; | 
        | 
|    311  | 
        | 
|    312     cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); | 
        | 
|    313     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    314     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    315     cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); | 
        | 
|    316     cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); | 
        | 
|    317     CU_ASSERT_PTR_EQUAL(begin, &nodes[2]) | 
        | 
|    318     CU_ASSERT_PTR_EQUAL(end, &nodes[0]) | 
        | 
|    319     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) | 
        | 
|    320     CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) | 
        | 
|    321     CU_ASSERT_PTR_NULL(nodes[1].prev) | 
        | 
|    322     CU_ASSERT_PTR_NULL(nodes[0].prev) | 
        | 
|    323 } | 
        | 
|    324  | 
        | 
|    325 void test_linked_list_insert(void) { | 
        | 
|    326     struct node nodes[4]; | 
        | 
|    327     void *begin, *end; | 
        | 
|    328  | 
        | 
|    329     // insert mid list | 
        | 
|    330     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    331     begin = &nodes[0]; | 
        | 
|    332     end = &nodes[2]; | 
        | 
|    333  | 
        | 
|    334     cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); | 
        | 
|    335     cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); | 
        | 
|    336  | 
        | 
|    337     cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); | 
        | 
|    338     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    339     CU_ASSERT_PTR_EQUAL(end, &nodes[2]) | 
        | 
|    340     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[3]) | 
        | 
|    341     CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[3]) | 
        | 
|    342     CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[1]) | 
        | 
|    343     CU_ASSERT_PTR_EQUAL(nodes[3].next, &nodes[2]) | 
        | 
|    344  | 
        | 
|    345     // insert end | 
        | 
|    346     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    347     begin = &nodes[0]; | 
        | 
|    348     end = &nodes[2]; | 
        | 
|    349  | 
        | 
|    350     cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); | 
        | 
|    351     cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); | 
        | 
|    352  | 
        | 
|    353     cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); | 
        | 
|    354     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    355     CU_ASSERT_PTR_EQUAL(end, &nodes[3]) | 
        | 
|    356     CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[3]) | 
        | 
|    357     CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[2]) | 
        | 
|    358     CU_ASSERT_PTR_NULL(nodes[3].next) | 
        | 
|    359  | 
        | 
|    360     // insert begin | 
        | 
|    361     memset(nodes, 0, 4 * sizeof(struct node)); | 
        | 
|    362     begin = &nodes[0]; | 
        | 
|    363     end = &nodes[2]; | 
        | 
|    364  | 
        | 
|    365     cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); | 
        | 
|    366     cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); | 
        | 
|    367  | 
        | 
|    368     cx_linked_list_insert(&begin, &end, loc_prev, loc_next, NULL, &nodes[3]); | 
        | 
|    369     CU_ASSERT_PTR_EQUAL(begin, &nodes[3]) | 
        | 
|    370     CU_ASSERT_PTR_EQUAL(end, &nodes[2]) | 
        | 
|    371     CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[3]) | 
        | 
|    372     CU_ASSERT_PTR_NULL(nodes[3].prev) | 
        | 
|    373     CU_ASSERT_PTR_EQUAL(nodes[3].next, &nodes[0]) | 
        | 
|    374 } | 
        | 
|    375  | 
        | 
|    376 void test_linked_list_insert_chain(void) { | 
        | 
|    377     struct node nodes[5]; | 
        | 
|    378     void *begin, *end; | 
        | 
|    379  | 
        | 
|    380     // insert mid list | 
        | 
|    381     memset(nodes, 0, 5 * sizeof(struct node)); | 
        | 
|    382     begin = &nodes[0]; | 
        | 
|    383     end = &nodes[2]; | 
        | 
|    384  | 
        | 
|    385     cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); | 
        | 
|    386     cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); | 
        | 
|    387     cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); | 
        | 
|    388  | 
        | 
|    389     cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], NULL); | 
        | 
|    390     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    391     CU_ASSERT_PTR_EQUAL(end, &nodes[2]) | 
        | 
|    392     CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[3]) | 
        | 
|    393     CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[4]) | 
        | 
|    394     CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[1]) | 
        | 
|    395     CU_ASSERT_PTR_EQUAL(nodes[4].next, &nodes[2]) | 
        | 
|    396  | 
        | 
|    397     // insert end | 
        | 
|    398     memset(nodes, 0, 5 * sizeof(struct node)); | 
        | 
|    399     begin = &nodes[0]; | 
        | 
|    400     end = &nodes[2]; | 
        | 
|    401  | 
        | 
|    402     cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); | 
        | 
|    403     cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); | 
        | 
|    404     cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); | 
        | 
|    405  | 
        | 
|    406     cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], NULL); | 
        | 
|    407     CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) | 
        | 
|    408     CU_ASSERT_PTR_EQUAL(end, &nodes[4]) | 
        | 
|    409     CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[3]) | 
        | 
|    410     CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[2]) | 
        | 
|    411     CU_ASSERT_PTR_NULL(nodes[4].next) | 
        | 
|    412  | 
        | 
|    413     // insert begin | 
        | 
|    414     memset(nodes, 0, 5 * sizeof(struct node)); | 
        | 
|    415     begin = &nodes[0]; | 
        | 
|    416     end = &nodes[2]; | 
        | 
|    417  | 
        | 
|    418     cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); | 
        | 
|    419     cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); | 
        | 
|    420     cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); | 
        | 
|    421  | 
        | 
|    422     cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, NULL, &nodes[3], NULL); | 
        | 
|    423     CU_ASSERT_PTR_EQUAL(begin, &nodes[3]) | 
        | 
|    424     CU_ASSERT_PTR_EQUAL(end, &nodes[2]) | 
        | 
|    425     CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[4]) | 
        | 
|    426     CU_ASSERT_PTR_NULL(nodes[3].prev) | 
        | 
|    427     CU_ASSERT_PTR_EQUAL(nodes[4].next, &nodes[0]) | 
        | 
|    428 } | 
        | 
|    429  | 
        | 
|    430 void test_linked_list_first(void) { | 
        | 
|    431     struct node *begin = create_nodes_test_data(3, NULL); | 
        | 
|    432     CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin, loc_prev), begin) | 
        | 
|    433     CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next, loc_prev), begin) | 
        | 
|    434     CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next->next, loc_prev), begin) | 
        | 
|    435     destroy_nodes_test_data(begin); | 
        | 
|    436 } | 
        | 
|    437  | 
        | 
|    438 void test_linked_list_last(void) { | 
        | 
|    439     struct node *begin = create_nodes_test_data(3, NULL); | 
        | 
|    440     struct node *end = begin->next->next; | 
        | 
|    441     CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin, loc_next), end) | 
        | 
|    442     CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next, loc_next), end) | 
        | 
|    443     CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next->next, loc_next), end) | 
        | 
|    444     destroy_nodes_test_data(begin); | 
        | 
|    445 } | 
        | 
|    446  | 
        | 
|    447 void test_linked_list_prev(void) { | 
        | 
|    448     struct node *begin = create_nodes_test_data(3, NULL); | 
        | 
|    449     CU_ASSERT_PTR_NULL(cx_linked_list_prev(begin, loc_next, begin)) | 
        | 
|    450     CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next), begin) | 
        | 
|    451     CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next) | 
        | 
|    452     destroy_nodes_test_data(begin); | 
        | 
|    453 } | 
        | 
|    454  | 
        | 
|    455 void test_linked_list_remove(void) { | 
        | 
|    456     void *begin, *end; | 
        | 
|    457  | 
        | 
|    458     int data[] = {2, 4, 6}; | 
        | 
|    459     begin = create_nodes_test_data(3, data); | 
        | 
|    460     struct node *first = begin; | 
        | 
|    461     struct node *second = first->next; | 
        | 
|    462     struct node *third = second->next; | 
        | 
|    463     end = third; | 
        | 
|    464  | 
        | 
|    465     cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); | 
        | 
|    466     CU_ASSERT_PTR_EQUAL(begin, first) | 
        | 
|    467     CU_ASSERT_PTR_EQUAL(end, third) | 
        | 
|    468     CU_ASSERT_PTR_NULL(first->prev) | 
        | 
|    469     CU_ASSERT_PTR_EQUAL(first->next, third) | 
        | 
|    470     CU_ASSERT_PTR_EQUAL(third->prev, first) | 
        | 
|    471     CU_ASSERT_PTR_NULL(third->next) | 
        | 
|    472  | 
        | 
|    473     cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); | 
        | 
|    474     CU_ASSERT_PTR_EQUAL(begin, first) | 
        | 
|    475     CU_ASSERT_PTR_EQUAL(end, first) | 
        | 
|    476     CU_ASSERT_PTR_NULL(first->prev) | 
        | 
|    477     CU_ASSERT_PTR_NULL(first->next) | 
        | 
|    478  | 
        | 
|    479     cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); | 
        | 
|    480     CU_ASSERT_PTR_NULL(begin) | 
        | 
|    481     CU_ASSERT_PTR_NULL(end) | 
        | 
|    482  | 
        | 
|    483     free(first); | 
        | 
|    484     free(second); | 
        | 
|    485     free(third); | 
        | 
|    486 } | 
        | 
|    487  | 
        | 
|    488 void test_linked_list_size(void) { | 
        | 
|    489     struct node *list; | 
        | 
|    490  | 
        | 
|    491     CU_ASSERT_PTR_EQUAL(cx_linked_list_size(NULL, loc_next), 0) | 
        | 
|    492  | 
        | 
|    493     list = create_nodes_test_data(5, NULL); | 
        | 
|    494     CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 5) | 
        | 
|    495     destroy_nodes_test_data(list); | 
        | 
|    496  | 
        | 
|    497     list = create_nodes_test_data(13, NULL); | 
        | 
|    498     CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 13) | 
        | 
|    499     destroy_nodes_test_data(list); | 
        | 
|    500 } | 
        | 
|    501  | 
        | 
|    502 void test_linked_list_sort(void) { | 
        | 
|    503     int expected[] = { | 
        | 
|    504             14, 30, 151, 163, 227, 300, 315, 317, 363, 398, 417, 424, 438, 446, 508, 555, 605, 713, 716, 759, 761, 880, | 
        | 
|    505             894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 1707, 1734, 1771, 1874, 1894, | 
        | 
|    506             1976, 2079, 2124, 2130, 2135, 2266, 2338, 2358, 2430, 2500, 2540, 2542, 2546, 2711, 2733, 2754, 2764, 2797, | 
        | 
|    507             2888, 2900, 3020, 3053, 3109, 3244, 3275, 3302, 3362, 3363, 3364, 3441, 3515, 3539, 3579, 3655, 3675, 3677, | 
        | 
|    508             3718, 3724, 3757, 3866, 3896, 3906, 3941, 3984, 3994, 4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681, | 
        | 
|    509             4785, 4791, 4801, 4859, 4903, 4973 | 
        | 
|    510     }; | 
        | 
|    511     int scrambled[] = { | 
        | 
|    512             759, 716, 880, 761, 2358, 2542, 2500, 2540, 2546, 2711, 2430, 1707, 1874, 1771, 1894, 1734, 1976, 2079, | 
        | 
|    513             2124, 2130, 2135, 2266, 2338, 2733, 2754, 2764, 2797, 3362, 3363, 3364, 3441, 3515, 3539, 3579, 3655, 2888, | 
        | 
|    514             2900, 3020, 3053, 3109, 3244, 3275, 3302, 438, 446, 508, 555, 605, 713, 14, 30, 151, 163, 227, 300, | 
        | 
|    515             894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 315, 317, 363, 398, 417, 424, | 
        | 
|    516             3675, 3677, 3718, 3724, 3757, 3866, 3896, 3906, 3941, 3984, 3994, 4785, 4791, 4801, 4859, 4903, 4973, | 
        | 
|    517             4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681 | 
        | 
|    518     }; | 
        | 
|    519  | 
        | 
|    520     void *begin = create_nodes_test_data(100, scrambled); | 
        | 
|    521     void *end = cx_linked_list_last(begin, loc_next); | 
        | 
|    522  | 
        | 
|    523     cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, | 
        | 
|    524                         false, cmp_int); | 
        | 
|    525  | 
        | 
|    526     struct node *check = begin; | 
        | 
|    527     struct node *check_last = NULL; | 
        | 
|    528     CU_ASSERT_PTR_NULL(check->prev) | 
        | 
|    529     CU_ASSERT_EQUAL(check->data, expected[0]) | 
        | 
|    530     cx_for_n (i, 100) { | 
        | 
|    531         CU_ASSERT_EQUAL(check->data, expected[i]) | 
        | 
|    532         CU_ASSERT_PTR_EQUAL(check->prev, check_last) | 
        | 
|    533         if (i < 99) { | 
        | 
|    534             CU_ASSERT_PTR_NOT_NULL(check->next) | 
        | 
|    535         } | 
        | 
|    536         check_last = check; | 
        | 
|    537         check = check->next; | 
        | 
|    538     } | 
        | 
|    539     CU_ASSERT_PTR_NULL(check) | 
        | 
|    540     CU_ASSERT_PTR_EQUAL(end, check_last) | 
        | 
|    541  | 
        | 
|    542     destroy_nodes_test_data(begin); | 
        | 
|    543 } | 
        | 
|    544  | 
        | 
|    545 void test_linked_list_reverse(void) { | 
        | 
|    546     void *begin, *end; | 
        | 
|    547  | 
        | 
|    548     int data[] = {2, 4, 6, 8}; | 
        | 
|    549     int reversed[] = {8, 6, 4, 2}; | 
        | 
|    550  | 
        | 
|    551     void *list = create_nodes_test_data(4, data); | 
        | 
|    552     void *expected = create_nodes_test_data(4, reversed); | 
        | 
|    553  | 
        | 
|    554     begin = list; | 
        | 
|    555     end = cx_linked_list_last(list, loc_next); | 
        | 
|    556  | 
        | 
|    557     cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); | 
        | 
|    558     CU_ASSERT_PTR_EQUAL(end, list) | 
        | 
|    559     CU_ASSERT_PTR_EQUAL(begin, cx_linked_list_first(end, loc_prev)) | 
        | 
|    560     CU_ASSERT_TRUE(0 == cx_linked_list_compare(begin, expected, loc_next, loc_data, | 
        | 
|    561                                                0, cmp_int)) | 
        | 
|    562  | 
        | 
|    563     destroy_nodes_test_data(begin); | 
        | 
|    564     destroy_nodes_test_data(expected); | 
        | 
|    565 } | 
        | 
|    566  | 
        | 
|    567 static void verify_linked_list_create(CxList *list) { | 
        | 
|    568     CU_ASSERT_EQUAL(list->size, 0) | 
        | 
|    569     CU_ASSERT_EQUAL(list->capacity, (size_t) -1) | 
        | 
|    570     CU_ASSERT_PTR_EQUAL(list->allocator, cxTestingAllocator) | 
        | 
|    571     CU_ASSERT_PTR_EQUAL(list->cmpfunc, cmp_int) | 
        | 
|    572  | 
        | 
|    573     cxListDestroy(list); | 
        | 
|    574 } | 
        | 
|    575  | 
        | 
|    576 void test_hl_linked_list_create(void) { | 
        | 
|    577     CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); | 
        | 
|    578     CU_ASSERT_EQUAL(list->itemsize, sizeof(int)) | 
        | 
|    579     verify_linked_list_create(list); | 
        | 
|    580 } | 
        | 
|    581  | 
        | 
|    582 void test_hl_ptr_linked_list_create(void) { | 
        | 
|    583     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    584     CU_ASSERT_EQUAL(list->itemsize, sizeof(void *)) | 
        | 
|    585     verify_linked_list_create(list); | 
        | 
|    586 } | 
        | 
|    587  | 
        | 
|    588 void test_hl_linked_list_from_array(void) { | 
        | 
|    589     int data[] = {2, 4, 5, 7, 10, 15}; | 
        | 
|    590  | 
        | 
|    591     CxList *expected = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); | 
        | 
|    592     cx_for_n (i, 5) cxListAdd(expected, &data[i]); | 
        | 
|    593  | 
        | 
|    594     CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, data); | 
        | 
|    595  | 
        | 
|    596     CU_ASSERT_TRUE(0 == cxListCompare(list, expected)) | 
        | 
|    597  | 
        | 
|    598     cxListDestroy(list); | 
        | 
|    599     cxListDestroy(expected); | 
        | 
|    600 } | 
        | 
|    601  | 
        | 
|    602 static void verify_hl_linked_list_add( | 
        | 
|    603         CxList *list, | 
        | 
|    604         int data[], | 
        | 
|    605         size_t len, | 
        | 
|    606         bool write_through | 
        | 
|    607 ) { | 
        | 
|    608     cx_for_n (i, len) CU_ASSERT_EQUAL(cxListAdd(list, &data[i]), 0) | 
        | 
|    609     CU_ASSERT_EQUAL(list->size, len) | 
        | 
|    610     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    611     cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) | 
        | 
|    612     cx_for_n (i, len) ++data[i]; | 
        | 
|    613     if (write_through) { | 
        | 
|    614         cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) | 
        | 
|    615     } else { | 
        | 
|    616         cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i] - 1) | 
        | 
|    617     } | 
        | 
|    618     cxListDestroy(list); | 
        | 
|    619 } | 
        | 
|    620  | 
        | 
|    621 void test_hl_linked_list_add(void) { | 
        | 
|    622     CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); | 
        | 
|    623     int data[] = {5, 47, 13, 9, 18, 1, 42}; | 
        | 
|    624     verify_hl_linked_list_add(list, data, sizeof(data) / sizeof(int), false); | 
        | 
|    625 } | 
        | 
|    626  | 
        | 
|    627 void test_hl_ptr_linked_list_add(void) { | 
        | 
|    628     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    629     int data[] = {5, 47, 84, 13, 9, 18, 90, 1, 42}; | 
        | 
|    630     verify_hl_linked_list_add(list, data, sizeof(data) / sizeof(int), true); | 
        | 
|    631 } | 
        | 
|    632  | 
        | 
|    633 static void verify_hl_linked_list_insert(CxList *list) { | 
        | 
|    634     int a = 5, b = 47, c = 13, d = 42; | 
        | 
|    635  | 
        | 
|    636     CU_ASSERT_NOT_EQUAL(cxListInsert(list, 1, &a), 0) | 
        | 
|    637     CU_ASSERT_EQUAL(list->size, 0) | 
        | 
|    638     CU_ASSERT_EQUAL(cxListInsert(list, 0, &a), 0) | 
        | 
|    639     CU_ASSERT_EQUAL(list->size, 1) | 
        | 
|    640     CU_ASSERT_EQUAL(cxListInsert(list, 0, &b), 0) | 
        | 
|    641     CU_ASSERT_EQUAL(list->size, 2) | 
        | 
|    642     CU_ASSERT_EQUAL(cxListInsert(list, 1, &c), 0) | 
        | 
|    643     CU_ASSERT_EQUAL(list->size, 3) | 
        | 
|    644     CU_ASSERT_EQUAL(cxListInsert(list, 3, &d), 0) | 
        | 
|    645  | 
        | 
|    646     CU_ASSERT_EQUAL(list->size, 4) | 
        | 
|    647     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    648  | 
        | 
|    649     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) | 
        | 
|    650     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 13) | 
        | 
|    651     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 5) | 
        | 
|    652     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 3), 42) | 
        | 
|    653  | 
        | 
|    654     cxListDestroy(list); | 
        | 
|    655 } | 
        | 
|    656  | 
        | 
|    657 void test_hl_linked_list_insert(void) { | 
        | 
|    658     verify_hl_linked_list_insert(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int))); | 
        | 
|    659 } | 
        | 
|    660  | 
        | 
|    661 void test_hl_ptr_linked_list_insert(void) { | 
        | 
|    662     verify_hl_linked_list_insert(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); | 
        | 
|    663 } | 
        | 
|    664  | 
        | 
|    665 static void verify_hl_linked_list_remove(CxList *list) { | 
        | 
|    666     CU_ASSERT_EQUAL(list->size, 4) | 
        | 
|    667     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    668  | 
        | 
|    669     CU_ASSERT_NOT_EQUAL(cxListRemove(list, 4), 0) | 
        | 
|    670  | 
        | 
|    671     CU_ASSERT_EQUAL(cxListRemove(list, 2), 0) | 
        | 
|    672     CU_ASSERT_EQUAL(list->size, 3) | 
        | 
|    673     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    674     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 5) | 
        | 
|    675     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 47) | 
        | 
|    676     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 13) | 
        | 
|    677  | 
        | 
|    678     CU_ASSERT_EQUAL(cxListRemove(list, 0), 0) | 
        | 
|    679     CU_ASSERT_EQUAL(list->size, 2) | 
        | 
|    680     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    681     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) | 
        | 
|    682     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 13) | 
        | 
|    683  | 
        | 
|    684     CU_ASSERT_EQUAL(cxListRemove(list, 1), 0) | 
        | 
|    685     CU_ASSERT_EQUAL(list->size, 1) | 
        | 
|    686     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    687     CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) | 
        | 
|    688  | 
        | 
|    689     CU_ASSERT_EQUAL(cxListRemove(list, 0), 0) | 
        | 
|    690     CU_ASSERT_EQUAL(list->size, 0) | 
        | 
|    691     CU_ASSERT_TRUE(list->capacity >= list->size) | 
        | 
|    692  | 
        | 
|    693     CU_ASSERT_NOT_EQUAL(cxListRemove(list, 0), 0) | 
        | 
|    694  | 
        | 
|    695     cxListDestroy(list); | 
        | 
|    696 } | 
        | 
|    697  | 
        | 
|    698 void test_hl_linked_list_remove(void) { | 
        | 
|    699     int data[] = {5, 47, 42, 13}; | 
        | 
|    700     CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, | 
        | 
|    701                                          sizeof(int), 4, data); | 
        | 
|    702     verify_hl_linked_list_remove(list); | 
        | 
|    703 } | 
        | 
|    704  | 
        | 
|    705 void test_hl_ptr_linked_list_remove(void) { | 
        | 
|    706     int a = 5, b = 47, c = 42, d = 13; | 
        | 
|    707     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    708     cxListAdd(list, &a); | 
        | 
|    709     cxListAdd(list, &b); | 
        | 
|    710     cxListAdd(list, &c); | 
        | 
|    711     cxListAdd(list, &d); | 
        | 
|    712     verify_hl_linked_list_remove(list); | 
        | 
|    713 } | 
        | 
|    714  | 
        | 
|    715 static void verify_hl_linked_list_at( | 
        | 
|    716         CxList *list, | 
        | 
|    717         size_t len, | 
        | 
|    718         int *data | 
        | 
|    719 ) { | 
        | 
|    720     CU_ASSERT_EQUAL(list->size, len) | 
        | 
|    721     cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) | 
        | 
|    722     CU_ASSERT_PTR_NULL(cxListAt(list, len)) | 
        | 
|    723     free(data); | 
        | 
|    724     cxListDestroy(list); | 
        | 
|    725 } | 
        | 
|    726  | 
        | 
|    727 void test_hl_linked_list_at(void) { | 
        | 
|    728     size_t len = 100; | 
        | 
|    729     int *data = create_ints_test_data(len); | 
        | 
|    730     CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, | 
        | 
|    731                                          sizeof(int), len, data); | 
        | 
|    732     verify_hl_linked_list_at(list, len, data); | 
        | 
|    733 } | 
        | 
|    734  | 
        | 
|    735 void test_hl_ptr_linked_list_at(void) { | 
        | 
|    736     size_t len = 250; | 
        | 
|    737     int *data = create_ints_test_data(len); | 
        | 
|    738     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    739     cx_for_n (i, len) cxListAdd(list, &data[i]); | 
        | 
|    740     verify_hl_linked_list_at(list, len, data); | 
        | 
|    741 } | 
        | 
|    742  | 
        | 
|    743 static void verify_hl_linked_list_find( | 
        | 
|    744         CxList *list, | 
        | 
|    745         size_t len, | 
        | 
|    746         int *data | 
        | 
|    747 ) { | 
        | 
|    748     cx_for_n (attempt, 100) { | 
        | 
|    749         size_t exp = rand() % len; // NOLINT(cert-msc50-cpp) | 
        | 
|    750         int val = data[exp]; | 
        | 
|    751         cx_for_n (i, exp) { | 
        | 
|    752             if (data[i] == val) { | 
        | 
|    753                 exp = i; | 
        | 
|    754                 break; | 
        | 
|    755             } | 
        | 
|    756         } | 
        | 
|    757         CU_ASSERT_EQUAL(cxListFind(list, &val), exp) | 
        | 
|    758     } | 
        | 
|    759     free(data); | 
        | 
|    760     cxListDestroy(list); | 
        | 
|    761 } | 
        | 
|    762  | 
        | 
|    763 void test_hl_linked_list_find(void) { | 
        | 
|    764     size_t len = 100; | 
        | 
|    765     int *data = create_ints_test_data(len); | 
        | 
|    766     CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), len, data); | 
        | 
|    767     verify_hl_linked_list_find(list, len, data); | 
        | 
|    768 } | 
        | 
|    769  | 
        | 
|    770 void test_hl_ptr_linked_list_find(void) { | 
        | 
|    771     size_t len = 250; | 
        | 
|    772     int *data = create_ints_test_data(len); | 
        | 
|    773     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    774     cx_for_n (i, len) cxListAdd(list, &data[i]); | 
        | 
|    775     verify_hl_linked_list_find(list, len, data); | 
        | 
|    776 } | 
        | 
|    777  | 
        | 
|    778 struct sort_test_data { | 
        | 
|    779     size_t len; | 
        | 
|    780     int *data; | 
        | 
|    781     int *sorted; | 
        | 
|    782 }; | 
        | 
|    783  | 
        | 
|    784 static struct sort_test_data create_sort_test_data(void) { | 
        | 
|    785     size_t len = 1000; | 
        | 
|    786     int *data = create_ints_test_data(len); | 
        | 
|    787     int *sorted = malloc(sizeof(int) * len); | 
        | 
|    788     memcpy(sorted, data, sizeof(int) * len); | 
        | 
|    789     qsort(sorted, len, sizeof(int), cmp_int); | 
        | 
|    790     struct sort_test_data s = {len, data, sorted}; | 
        | 
|    791     return s; | 
        | 
|    792 } | 
        | 
|    793  | 
        | 
|    794 static void free_sort_test_data(struct sort_test_data s) { | 
        | 
|    795     free(s.data); | 
        | 
|    796     free(s.sorted); | 
        | 
|    797 } | 
        | 
|    798  | 
        | 
|    799 static void verify_hl_linked_list_sort( | 
        | 
|    800         CxList *list, | 
        | 
|    801         struct sort_test_data td | 
        | 
|    802 ) { | 
        | 
|    803     cxListSort(list); | 
        | 
|    804     cx_for_n (i, td.len) CU_ASSERT_EQUAL_FATAL(*(int *) cxListAt(list, i), td.sorted[i]) | 
        | 
|    805     free_sort_test_data(td); | 
        | 
|    806     cxListDestroy(list); | 
        | 
|    807 } | 
        | 
|    808  | 
        | 
|    809 void test_hl_linked_list_sort(void) { | 
        | 
|    810     struct sort_test_data td = create_sort_test_data(); | 
        | 
|    811     CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), td.len, td.data); | 
        | 
|    812     verify_hl_linked_list_sort(list, td); | 
        | 
|    813 } | 
        | 
|    814  | 
        | 
|    815 void test_hl_ptr_linked_list_sort(void) { | 
        | 
|    816     struct sort_test_data td = create_sort_test_data(); | 
        | 
|    817     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    818     cx_for_n (i, td.len) cxListAdd(list, &td.data[i]); | 
        | 
|    819     verify_hl_linked_list_sort(list, td); | 
        | 
|    820 } | 
        | 
|    821  | 
        | 
|    822 void verify_hl_linked_list_iterator(CxList *list) { | 
        | 
|    823     int i = 0; | 
        | 
|    824     CxIterator iter = cxListBegin(list); | 
        | 
|    825     cx_foreach(int*, x, iter) { | 
        | 
|    826         CU_ASSERT_EQUAL(iter.index, (size_t) (i + 1) / 2) | 
        | 
|    827         CU_ASSERT_EQUAL(*x, i) | 
        | 
|    828         if (*x % 2 == 1) iter.remove = true; | 
        | 
|    829         i++; | 
        | 
|    830     } | 
        | 
|    831     CU_ASSERT_EQUAL(i, 10) | 
        | 
|    832     CU_ASSERT_EQUAL_FATAL(list->size, 5) | 
        | 
|    833     cx_for_n(j, 5) CU_ASSERT_EQUAL(*(int *) cxListAt(list, j), (int) j * 2) | 
        | 
|    834     cxListDestroy(list); | 
        | 
|    835 } | 
        | 
|    836  | 
        | 
|    837 void test_hl_linked_list_iterator(void) { | 
        | 
|    838     CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); | 
        | 
|    839     cx_for_n (i, 10) cxListAdd(list, &i); | 
        | 
|    840     verify_hl_linked_list_iterator(list); | 
        | 
|    841 } | 
        | 
|    842  | 
        | 
|    843 void test_hl_ptr_linked_list_iterator(void) { | 
        | 
|    844     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    845     int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; | 
        | 
|    846     cx_for_n (i, 10) cxListAdd(list, &data[i]); | 
        | 
|    847     verify_hl_linked_list_iterator(list); | 
        | 
|    848 } | 
        | 
|    849  | 
        | 
|    850 static void verify_hl_linked_list_insert_via_iterator( | 
        | 
|    851         CxList *list, | 
        | 
|    852         int *testdata | 
        | 
|    853 ) { | 
        | 
|    854     CxIterator iter = cxListIterator(list, 2); | 
        | 
|    855     CU_ASSERT_EQUAL(iter.index, 2) | 
        | 
|    856     CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) | 
        | 
|    857     size_t i = 4; | 
        | 
|    858  | 
        | 
|    859     ++i; | 
        | 
|    860     cxListInsertAfter(&iter, &testdata[i]); | 
        | 
|    861     CU_ASSERT_EQUAL(iter.index, 2) | 
        | 
|    862     CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) | 
        | 
|    863     ++i; | 
        | 
|    864     cxListInsertBefore(&iter, &testdata[i]); | 
        | 
|    865     CU_ASSERT_EQUAL(iter.index, 3) | 
        | 
|    866     CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) | 
        | 
|    867  | 
        | 
|    868     iter = cxListBegin(list); | 
        | 
|    869     ++i; | 
        | 
|    870     cxListInsertBefore(&iter, &testdata[i]); | 
        | 
|    871     CU_ASSERT_EQUAL(iter.index, 1) | 
        | 
|    872     CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 0) | 
        | 
|    873     iter = cxListIterator(list, list->size); | 
        | 
|    874     ++i; | 
        | 
|    875     cxListInsertBefore(&iter, &testdata[i]); | 
        | 
|    876     CU_ASSERT_EQUAL(iter.index, 9) | 
        | 
|    877     CU_ASSERT_FALSE(cxIteratorValid(&iter)) | 
        | 
|    878     iter = cxListIterator(list, list->size); | 
        | 
|    879     ++i; | 
        | 
|    880     cxListInsertAfter(&iter, &testdata[i]); | 
        | 
|    881     CU_ASSERT_EQUAL(iter.index, 10) | 
        | 
|    882     CU_ASSERT_FALSE(cxIteratorValid(&iter)) | 
        | 
|    883  | 
        | 
|    884     int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; | 
        | 
|    885     cx_for_n (j, 10) CU_ASSERT_EQUAL(*(int *) cxListAt(list, j), expdata[j]) | 
        | 
|    886     cxListDestroy(list); | 
        | 
|    887 } | 
        | 
|    888  | 
        | 
|    889 void test_hl_linked_list_insert_via_iterator(void) { | 
        | 
|    890     int testdata[] = {0, 1, 2, 3, 4, 10, 20, 30, 40, 50}; | 
        | 
|    891     // only add the first five elements, the remaining five will be inserted | 
        | 
|    892     CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, testdata); | 
        | 
|    893     verify_hl_linked_list_insert_via_iterator(list, testdata); | 
        | 
|    894 } | 
        | 
|    895  | 
        | 
|    896 void test_hl_ptr_linked_list_insert_via_iterator(void) { | 
        | 
|    897     int testdata[] = {0, 1, 2, 3, 4, 10, 20, 30, 40, 50}; | 
        | 
|    898     CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); | 
        | 
|    899     // only add the first five elements, the remaining five will be inserted | 
        | 
|    900     cx_for_n (i, 5) cxListAdd(list, &testdata[i]); | 
        | 
|    901     verify_hl_linked_list_insert_via_iterator(list, testdata); | 
        | 
|    902 } | 
        | 
|    903  | 
        | 
|    904 static void test_setup_allocator(void) { | 
        | 
|    905     cxTestingAllocatorReset(); | 
        | 
|    906 } | 
        | 
|    907  | 
        | 
|    908 static void test_verify_allocator(void) { | 
        | 
|    909     CU_ASSERT_TRUE(cxTestingAllocatorVerify()) | 
        | 
|    910 } | 
        | 
|    911  | 
        | 
|    912 int main() { | 
        | 
|    913     CU_pSuite suite = NULL; | 
        | 
|    914  | 
        | 
|    915     if (CUE_SUCCESS != CU_initialize_registry()) { | 
        | 
|    916         return CU_get_error(); | 
        | 
|    917     } | 
        | 
|    918  | 
        | 
|    919     suite = CU_add_suite("low level linked list", NULL, NULL); | 
        | 
|    920  | 
        | 
|    921     cu_add_test(suite, test_linked_list_link_unlink); | 
        | 
|    922     cu_add_test(suite, test_linked_list_at); | 
        | 
|    923     cu_add_test(suite, test_linked_list_find); | 
        | 
|    924     cu_add_test(suite, test_linked_list_compare); | 
        | 
|    925     cu_add_test(suite, test_linked_list_prepend); | 
        | 
|    926     cu_add_test(suite, test_linked_list_add); | 
        | 
|    927     cu_add_test(suite, test_linked_list_insert); | 
        | 
|    928     cu_add_test(suite, test_linked_list_insert_chain); | 
        | 
|    929     cu_add_test(suite, test_linked_list_first); | 
        | 
|    930     cu_add_test(suite, test_linked_list_last); | 
        | 
|    931     cu_add_test(suite, test_linked_list_prev); | 
        | 
|    932     cu_add_test(suite, test_linked_list_remove); | 
        | 
|    933     cu_add_test(suite, test_linked_list_size); | 
        | 
|    934     cu_add_test(suite, test_linked_list_sort); | 
        | 
|    935     cu_add_test(suite, test_linked_list_reverse); | 
        | 
|    936  | 
        | 
|    937     suite = CU_add_suite_with_setup_and_teardown( | 
        | 
|    938             "high level linked list", NULL, NULL, | 
        | 
|    939             test_setup_allocator, test_verify_allocator); | 
        | 
|    940  | 
        | 
|    941     cu_add_test(suite, test_hl_linked_list_create); | 
        | 
|    942     cu_add_test(suite, test_hl_linked_list_from_array); | 
        | 
|    943     cu_add_test(suite, test_hl_linked_list_add); | 
        | 
|    944     cu_add_test(suite, test_hl_linked_list_insert); | 
        | 
|    945     cu_add_test(suite, test_hl_linked_list_remove); | 
        | 
|    946     cu_add_test(suite, test_hl_linked_list_at); | 
        | 
|    947     cu_add_test(suite, test_hl_linked_list_find); | 
        | 
|    948     cu_add_test(suite, test_hl_linked_list_sort); | 
        | 
|    949     cu_add_test(suite, test_hl_linked_list_iterator); | 
        | 
|    950     cu_add_test(suite, test_hl_linked_list_insert_via_iterator); | 
        | 
|    951  | 
        | 
|    952     suite = CU_add_suite_with_setup_and_teardown( | 
        | 
|    953             "high level pointer linked list", NULL, NULL, | 
        | 
|    954             test_setup_allocator, test_verify_allocator); | 
        | 
|    955  | 
        | 
|    956     cu_add_test(suite, test_hl_ptr_linked_list_create); | 
        | 
|    957     cu_add_test(suite, test_hl_ptr_linked_list_add); | 
        | 
|    958     cu_add_test(suite, test_hl_ptr_linked_list_insert); | 
        | 
|    959     cu_add_test(suite, test_hl_ptr_linked_list_remove); | 
        | 
|    960     cu_add_test(suite, test_hl_ptr_linked_list_at); | 
        | 
|    961     cu_add_test(suite, test_hl_ptr_linked_list_find); | 
        | 
|    962     cu_add_test(suite, test_hl_ptr_linked_list_sort); | 
        | 
|    963     cu_add_test(suite, test_hl_ptr_linked_list_iterator); | 
        | 
|    964     cu_add_test(suite, test_hl_ptr_linked_list_insert_via_iterator); | 
        | 
|    965  | 
        | 
|    966     CU_basic_set_mode(UCX_CU_BRM); | 
        | 
|    967  | 
        | 
|    968     int exitcode; | 
        | 
|    969     if (CU_basic_run_tests()) { | 
        | 
|    970         exitcode = CU_get_error(); | 
        | 
|    971     } else { | 
        | 
|    972         exitcode = CU_get_number_of_failures() == 0 ? 0 : 1; | 
        | 
|    973     } | 
        | 
|    974     CU_cleanup_registry(); | 
        | 
|    975     return exitcode; | 
        | 
|    976 } | 
        |