tests/test_list.c

Tue, 09 Jan 2024 21:25:08 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 09 Jan 2024 21:25:08 +0100
changeset 800
1274e46b3013
parent 799
a2a757d225b4
child 801
04aa3913c0e3
permissions
-rw-r--r--

migrate cxEmptyList tests - relates to #342

     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/test.h"
    30 #include "util_allocator.h"
    31 #include "cx/compare.h"
    33 #include "cx/array_list.h"
    34 #include "cx/linked_list.h"
    36 #include <stdarg.h>
    38 typedef struct node {
    39     struct node *next;
    40     struct node *prev;
    41     int data;
    42 } node;
    44 const ptrdiff_t loc_prev = offsetof(struct node, prev);
    45 const ptrdiff_t loc_next = offsetof(struct node, next);
    46 const ptrdiff_t loc_data = offsetof(struct node, data);
    48 static node *create_nodes_test_data(size_t len) {
    49     node *begin = calloc(1, sizeof(node));
    50     void *prev = begin;
    51     for (size_t i = 1; i < len; i++) {
    52         node *n = calloc(1, sizeof(node));
    53         cx_linked_list_link(prev, n, loc_prev, loc_next);
    54         prev = n;
    55     }
    56     return begin;
    57 }
    59 void assign_nodes_test_data(node *n, ...) {
    60     va_list ap;
    61     va_start(ap, n);
    62     while (n != NULL) {
    63         n->data = va_arg(ap, int);
    64         n = n->next;
    65     }
    66     va_end(ap);
    67 }
    69 static void destroy_nodes_test_data(node *n) {
    70     while (n != NULL) {
    71         void *next = n->next;
    72         free(n);
    73         n = next;
    74     }
    75 }
    77 static int *int_test_data(size_t len) {
    78     int *data = malloc(len*sizeof(int));
    79     for (size_t i = 0 ; i < len ; i++) {
    80         data[i] = rand(); // NOLINT(*-msc50-cpp)
    81     }
    82     return data;
    83 }
    85 CX_TEST(test_linked_list_link_unlink) {
    86     node a = {0}, b = {0}, c = {0};
    88     CX_TEST_DO {
    89         cx_linked_list_link(&a, &b, loc_prev, loc_next);
    90         CX_TEST_ASSERT(a.prev == NULL);
    91         CX_TEST_ASSERT(a.next == &b);
    92         CX_TEST_ASSERT(b.prev == &a);
    93         CX_TEST_ASSERT(b.next == NULL);
    95         cx_linked_list_unlink(&a, &b, loc_prev, loc_next);
    96         CX_TEST_ASSERT(a.prev == NULL);
    97         CX_TEST_ASSERT(a.next == NULL);
    98         CX_TEST_ASSERT(b.prev == NULL);
    99         CX_TEST_ASSERT(b.next == NULL);
   101         cx_linked_list_link(&b, &c, loc_prev, loc_next);
   102         cx_linked_list_link(&a, &b, loc_prev, loc_next);
   103         cx_linked_list_unlink(&b, &c, loc_prev, loc_next);
   104         CX_TEST_ASSERT(a.prev == NULL);
   105         CX_TEST_ASSERT(a.next == &b);
   106         CX_TEST_ASSERT(b.prev == &a);
   107         CX_TEST_ASSERT(b.next == NULL);
   108         CX_TEST_ASSERT(c.prev == NULL);
   109         CX_TEST_ASSERT(c.next == NULL);
   110     }
   111 }
   113 CX_TEST(test_linked_list_at) {
   114     node a = {0}, b = {0}, c = {0}, d = {0};
   116     cx_linked_list_link(&a, &b, loc_prev, loc_next);
   117     cx_linked_list_link(&b, &c, loc_prev, loc_next);
   118     cx_linked_list_link(&c, &d, loc_prev, loc_next);
   120     CX_TEST_DO {
   121         CX_TEST_ASSERT(cx_linked_list_at(&a, 0, loc_next, 0) == &a);
   122         CX_TEST_ASSERT(cx_linked_list_at(&a, 0, loc_next, 1) == &b);
   123         CX_TEST_ASSERT(cx_linked_list_at(&a, 0, loc_next, 2) == &c);
   124         CX_TEST_ASSERT(cx_linked_list_at(&a, 0, loc_next, 3) == &d);
   125         CX_TEST_ASSERT(cx_linked_list_at(&a, 0, loc_next, 4) == NULL);
   126         CX_TEST_ASSERT(cx_linked_list_at(&b, 1, loc_prev, 0) == &a);
   127         CX_TEST_ASSERT(cx_linked_list_at(&b, 1, loc_next, 1) == &b);
   128         CX_TEST_ASSERT(cx_linked_list_at(&b, 1, loc_next, 2) == &c);
   129         CX_TEST_ASSERT(cx_linked_list_at(&b, 1, loc_next, 3) == &d);
   130         CX_TEST_ASSERT(cx_linked_list_at(&b, 1, loc_next, 4) == NULL);
   131         CX_TEST_ASSERT(cx_linked_list_at(&d, 3, loc_prev, 0) == &a);
   132         CX_TEST_ASSERT(cx_linked_list_at(&d, 3, loc_prev, 1) == &b);
   133     }
   134 }
   136 CX_TEST(test_linked_list_find) {
   137     void *list = create_nodes_test_data(4);
   138     assign_nodes_test_data(list, 2, 4, 6, 8);
   139     CX_TEST_DO {
   140         int s;
   141         s = 2;
   142         CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s) == 0);
   143         s = 4;
   144         CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s) == 1);
   145         s = 6;
   146         CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s) == 2);
   147         s = 8;
   148         CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s) == 3);
   149         s = 10;
   150         CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s) < 0);
   151         s = -2;
   152         CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s) < 0);
   153     }
   154     destroy_nodes_test_data(list);
   155 }
   157 CX_TEST(test_linked_list_compare) {
   158     void *la = create_nodes_test_data(4);
   159     void *lb = create_nodes_test_data(3);
   160     void *lc = create_nodes_test_data(4);
   161     assign_nodes_test_data(la, 2, 4, 6, 8);
   162     assign_nodes_test_data(lb, 2, 4, 6);
   163     assign_nodes_test_data(lc, 2, 4, 6, 9);
   164     CX_TEST_DO {
   165         CX_TEST_ASSERT(cx_linked_list_compare(la, lb, loc_next, loc_data, cx_cmp_int) > 0);
   166         CX_TEST_ASSERT(cx_linked_list_compare(lb, la, loc_next, loc_data, cx_cmp_int) < 0);
   167         CX_TEST_ASSERT(cx_linked_list_compare(lc, la, loc_next, loc_data, cx_cmp_int) > 0);
   168         CX_TEST_ASSERT(cx_linked_list_compare(la, lc, loc_next, loc_data, cx_cmp_int) < 0);
   169         CX_TEST_ASSERT(cx_linked_list_compare(la, la, loc_next, loc_data, cx_cmp_int) == 0);
   170     }
   171     destroy_nodes_test_data(la);
   172     destroy_nodes_test_data(lb);
   173     destroy_nodes_test_data(lc);
   174 }
   176 CX_TEST(test_linked_list_add) {
   177     node nodes[4];
   178     void *begin, *end;
   179     CX_TEST_DO {
   180         // test with begin, end / prev, next
   181         memset(nodes, 0, sizeof(node)*4);
   182         end = begin = NULL;
   184         cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]);
   185         CX_TEST_ASSERT(begin == &nodes[0]);
   186         CX_TEST_ASSERT(end == &nodes[0]);
   187         CX_TEST_ASSERT(nodes[0].prev == NULL);
   188         CX_TEST_ASSERT(nodes[0].next == NULL);
   190         cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]);
   191         CX_TEST_ASSERT(begin == &nodes[0]);
   192         CX_TEST_ASSERT(end == &nodes[1]);
   193         CX_TEST_ASSERT(nodes[0].next == &nodes[1]);
   194         CX_TEST_ASSERT(nodes[1].prev == &nodes[0]);
   196         // test with begin only / prev, next
   197         memset(nodes, 0, sizeof(node)*4);
   198         end = begin = NULL;
   200         cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]);
   201         CX_TEST_ASSERT(begin == &nodes[0]);
   202         cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[1]);
   203         CX_TEST_ASSERT(begin == &nodes[0]);
   204         CX_TEST_ASSERT(nodes[0].next == &nodes[1]);
   205         CX_TEST_ASSERT(nodes[1].prev == &nodes[0]);
   207         cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[2]);
   208         CX_TEST_ASSERT(nodes[1].next == &nodes[2]);
   209         CX_TEST_ASSERT(nodes[2].prev == &nodes[1]);
   211         // test with end only / prev, next
   212         memset(nodes, 0, sizeof(node)*4);
   213         end = begin = NULL;
   215         cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[0]);
   216         CX_TEST_ASSERT(end == &nodes[0]);
   217         cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[1]);
   218         CX_TEST_ASSERT(end == &nodes[1]);
   219         CX_TEST_ASSERT(nodes[0].next == &nodes[1]);
   220         CX_TEST_ASSERT(nodes[1].prev == &nodes[0]);
   222         cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[2]);
   223         CX_TEST_ASSERT(end == &nodes[2]);
   224         CX_TEST_ASSERT(nodes[1].next == &nodes[2]);
   225         CX_TEST_ASSERT(nodes[2].prev == &nodes[1]);
   227         // test with begin, end / next
   228         memset(nodes, 0, sizeof(node)*4);
   229         end = begin = NULL;
   231         cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]);
   232         CX_TEST_ASSERT(begin == &nodes[0]);
   233         CX_TEST_ASSERT(end == &nodes[0]);
   234         cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]);
   235         CX_TEST_ASSERT(end == &nodes[1]);
   236         CX_TEST_ASSERT(nodes[0].next == &nodes[1]);
   237         CX_TEST_ASSERT(nodes[1].prev == NULL);
   238     }
   239 }
   241 CX_TEST(test_linked_list_prepend) {
   242     node nodes[4];
   243     void *begin, *end;
   244     CX_TEST_DO {
   245         // test with begin, end / prev, next
   246         memset(nodes, 0, sizeof(node) * 4);
   247         end = begin = NULL;
   249         cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]);
   250         CX_TEST_ASSERT(begin == &nodes[0]);
   251         CX_TEST_ASSERT(end == &nodes[0]);
   252         CX_TEST_ASSERT(nodes[0].prev == NULL);
   253         CX_TEST_ASSERT(nodes[0].next == NULL);
   255         cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]);
   256         CX_TEST_ASSERT(begin == &nodes[1]);
   257         CX_TEST_ASSERT(end == &nodes[0]);
   258         CX_TEST_ASSERT(nodes[1].next == &nodes[0]);
   259         CX_TEST_ASSERT(nodes[0].prev == &nodes[1]);
   261         // test with begin only / prev, next
   262         memset(nodes, 0, sizeof(node) * 4);
   263         end = begin = NULL;
   265         cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[0]);
   266         CX_TEST_ASSERT(begin == &nodes[0]);
   267         cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[1]);
   268         CX_TEST_ASSERT(begin == &nodes[1]);
   269         CX_TEST_ASSERT(nodes[1].next == &nodes[0]);
   270         CX_TEST_ASSERT(nodes[0].prev == &nodes[1]);
   272         cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[2]);
   273         CX_TEST_ASSERT(begin == &nodes[2]);
   274         CX_TEST_ASSERT(nodes[2].next == &nodes[1]);
   275         CX_TEST_ASSERT(nodes[1].prev == &nodes[2]);
   277         // test with end only / prev, next
   278         memset(nodes, 0, sizeof(node) * 4);
   279         end = begin = NULL;
   281         cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[0]);
   282         CX_TEST_ASSERT(end == &nodes[0]);
   283         cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[1]);
   284         CX_TEST_ASSERT(end == &nodes[0]);
   285         CX_TEST_ASSERT(nodes[1].next == &nodes[0]);
   286         CX_TEST_ASSERT(nodes[0].prev == &nodes[1]);
   288         cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[2]);
   289         CX_TEST_ASSERT(end == &nodes[0]);
   290         CX_TEST_ASSERT(nodes[2].next == &nodes[1]);
   291         CX_TEST_ASSERT(nodes[1].prev == &nodes[2]);
   293         // test with begin, end / next
   294         memset(nodes, 0, sizeof(node) * 4);
   295         end = begin = NULL;
   297         cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]);
   298         CX_TEST_ASSERT(begin == &nodes[0]);
   299         CX_TEST_ASSERT(end == &nodes[0]);
   300         cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]);
   301         cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]);
   302         CX_TEST_ASSERT(begin == &nodes[2]);
   303         CX_TEST_ASSERT(end == &nodes[0]);
   304         CX_TEST_ASSERT(nodes[1].next == &nodes[0]);
   305         CX_TEST_ASSERT(nodes[2].next == &nodes[1]);
   306         CX_TEST_ASSERT(nodes[1].prev == NULL);
   307         CX_TEST_ASSERT(nodes[0].prev == NULL);
   308     }
   309 }
   311 CX_TEST(test_linked_list_insert) {
   312     node nodes[4];
   313     void *begin, *end;
   314     CX_TEST_DO {
   315         // insert mid list
   316         memset(nodes, 0, sizeof(node) * 4);
   317         begin = &nodes[0];
   318         end = &nodes[2];
   320         cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next);
   321         cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next);
   323         cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]);
   324         CX_TEST_ASSERT(begin == &nodes[0]);
   325         CX_TEST_ASSERT(end == &nodes[2]);
   326         CX_TEST_ASSERT(nodes[1].next == &nodes[3]);
   327         CX_TEST_ASSERT(nodes[2].prev == &nodes[3]);
   328         CX_TEST_ASSERT(nodes[3].prev == &nodes[1]);
   329         CX_TEST_ASSERT(nodes[3].next == &nodes[2]);
   331         // insert end
   332         memset(nodes, 0, sizeof(node) * 4);
   333         begin = &nodes[0];
   334         end = &nodes[2];
   336         cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next);
   337         cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next);
   339         cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]);
   340         CX_TEST_ASSERT(begin == &nodes[0]);
   341         CX_TEST_ASSERT(end == &nodes[3]);
   342         CX_TEST_ASSERT(nodes[2].next == &nodes[3]);
   343         CX_TEST_ASSERT(nodes[3].prev == &nodes[2]);
   344         CX_TEST_ASSERT(nodes[3].next == NULL);
   346         // insert begin
   347         memset(nodes, 0, sizeof(node) * 4);
   348         begin = &nodes[0];
   349         end = &nodes[2];
   351         cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next);
   352         cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next);
   354         cx_linked_list_insert(&begin, &end, loc_prev, loc_next, NULL, &nodes[3]);
   355         CX_TEST_ASSERT(begin == &nodes[3]);
   356         CX_TEST_ASSERT(end == &nodes[2]);
   357         CX_TEST_ASSERT(nodes[0].prev == &nodes[3]);
   358         CX_TEST_ASSERT(nodes[3].prev == NULL);
   359         CX_TEST_ASSERT(nodes[3].next == &nodes[0]);
   360     }
   361 }
   363 CX_TEST(test_linked_list_insert_chain) {
   364     node nodes[5];
   365     void *begin, *end;
   366     CX_TEST_DO {
   367         // insert mid list
   368         memset(nodes, 0, sizeof(node) * 5);
   369         begin = &nodes[0]; end = &nodes[2];
   371         cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next);
   372         cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next);
   373         cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next);
   375         cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], NULL);
   376         CX_TEST_ASSERT(begin == &nodes[0]);
   377         CX_TEST_ASSERT(end == &nodes[2]);
   378         CX_TEST_ASSERT(nodes[1].next == &nodes[3]);
   379         CX_TEST_ASSERT(nodes[2].prev == &nodes[4]);
   380         CX_TEST_ASSERT(nodes[3].prev == &nodes[1]);
   381         CX_TEST_ASSERT(nodes[4].next == &nodes[2]);
   383         // insert end
   384         memset(nodes, 0, sizeof(node) * 5);
   385         begin = &nodes[0]; end = &nodes[2];
   387         cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next);
   388         cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next);
   389         cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next);
   391         cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], NULL);
   392         CX_TEST_ASSERT(begin == &nodes[0]);
   393         CX_TEST_ASSERT(end == &nodes[4]);
   394         CX_TEST_ASSERT(nodes[2].next == &nodes[3]);
   395         CX_TEST_ASSERT(nodes[3].prev == &nodes[2]);
   396         CX_TEST_ASSERT(nodes[4].next == NULL);
   398         // insert begin
   399         memset(nodes, 0, sizeof(node) * 5);
   400         begin = &nodes[0]; end = &nodes[2];
   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);
   406         cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, NULL, &nodes[3], NULL);
   407         CX_TEST_ASSERT(begin == &nodes[3]);
   408         CX_TEST_ASSERT(end == &nodes[2]);
   409         CX_TEST_ASSERT(nodes[0].prev == &nodes[4]);
   410         CX_TEST_ASSERT(nodes[3].prev == NULL);
   411         CX_TEST_ASSERT(nodes[4].next == &nodes[0]);
   412     }
   413 }
   415 CX_TEST(test_linked_list_first) {
   416     node *testdata = create_nodes_test_data(3);
   417     void *begin = testdata;
   418     CX_TEST_DO {
   419         CX_TEST_ASSERT(begin == cx_linked_list_first(testdata, loc_prev));
   420         CX_TEST_ASSERT(begin == cx_linked_list_first(testdata->next, loc_prev));
   421         CX_TEST_ASSERT(begin == cx_linked_list_first(testdata->next->next, loc_prev));
   422     }
   423     destroy_nodes_test_data(testdata);
   424 }
   426 CX_TEST(test_linked_list_last) {
   427     node *testdata = create_nodes_test_data(3);
   428     void *end = testdata->next->next;
   429     CX_TEST_DO {
   430         CX_TEST_ASSERT(end == cx_linked_list_last(testdata, loc_next));
   431         CX_TEST_ASSERT(end == cx_linked_list_last(testdata->next, loc_next));
   432         CX_TEST_ASSERT(end == cx_linked_list_last(testdata->next->next, loc_next));
   433     }
   434     destroy_nodes_test_data(testdata);
   435 }
   437 CX_TEST(test_linked_list_prev) {
   438     node *testdata = create_nodes_test_data(3);
   439     CX_TEST_DO {
   440         CX_TEST_ASSERT(cx_linked_list_prev(testdata, loc_next, testdata) == NULL);
   441         CX_TEST_ASSERT(cx_linked_list_prev(testdata, loc_next, testdata->next) == testdata);
   442         CX_TEST_ASSERT(cx_linked_list_prev(testdata, loc_next, testdata->next->next) == testdata->next);
   443     }
   444     destroy_nodes_test_data(testdata);
   445 }
   447 CX_TEST(test_linked_list_remove) {
   448     node *testdata = create_nodes_test_data(3);
   449     assign_nodes_test_data(testdata, 2, 4, 6);
   450     node *first = testdata;
   451     node *second = first->next;
   452     node *third = second->next;
   453     void *begin = testdata;
   454     void *end = third;
   456     CX_TEST_DO {
   457         cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second);
   458         CX_TEST_ASSERT(begin == first);
   459         CX_TEST_ASSERT(end == third);
   460         CX_TEST_ASSERT(first->prev == NULL);
   461         CX_TEST_ASSERT(first->next == third);
   462         CX_TEST_ASSERT(third->prev == first);
   463         CX_TEST_ASSERT(third->next == NULL);
   465         cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third);
   466         CX_TEST_ASSERT(begin == first);
   467         CX_TEST_ASSERT(end == first);
   468         CX_TEST_ASSERT(first->prev == NULL);
   469         CX_TEST_ASSERT(first->next == NULL);
   471         cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first);
   472         CX_TEST_ASSERT(begin == NULL);
   473         CX_TEST_ASSERT(end == NULL);
   474     }
   475     // list is not intact anymore, we have to free nodes individually
   476     free(first);
   477     free(second);
   478     free(third);
   479 }
   481 CX_TEST(test_linked_list_size) {
   482     node *td5 = create_nodes_test_data(5);
   483     node *td13 = create_nodes_test_data(13);
   484     CX_TEST_DO {
   485         CX_TEST_ASSERT(cx_linked_list_size(NULL, loc_next) == 0);
   486         CX_TEST_ASSERT(cx_linked_list_size(td5, loc_next) == 5);
   487         CX_TEST_ASSERT(cx_linked_list_size(td13, loc_next) == 13);
   488     }
   489     destroy_nodes_test_data(td5);
   490     destroy_nodes_test_data(td13);
   491 }
   493 CX_TEST(test_linked_list_sort_empty) {
   494     void *begin = NULL;
   495     CX_TEST_DO {
   496         // cannot assert something, we can just test that it does not crash
   497         cx_linked_list_sort(&begin, NULL, loc_prev, loc_next, loc_data, cx_cmp_int);
   498         CX_TEST_ASSERT(true);
   499     }
   500 }
   502 CX_TEST(test_linked_list_sort) {
   503     const size_t len = 1500;
   504     int *testdata = int_test_data(len);
   505     void *scrambled = create_nodes_test_data(len);
   506     node *n = scrambled;
   507     for (size_t i = 0; i < len; i++) {
   508         n->data = testdata[i];
   509         n = n->next;
   510     }
   511     int *sorted = malloc(len*sizeof(int));
   512     memcpy(sorted, testdata, len*sizeof(int));
   513     qsort(sorted, len, sizeof(int), cx_cmp_int);
   515     void *begin = scrambled;
   516     void *end = cx_linked_list_last(begin, loc_next);
   518     CX_TEST_DO {
   519         cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, cx_cmp_int);
   520         node *check = begin;
   521         node *check_last = NULL;
   522         for (size_t i = 0; i < len; i++) {
   523             CX_TEST_ASSERT(check->data == sorted[i]);
   524             CX_TEST_ASSERT(check->prev == check_last);
   525             if (i < len - 1) {
   526                 CX_TEST_ASSERT(check->next != NULL);
   527             }
   528             check_last = check;
   529             check = check->next;
   530         }
   531         CX_TEST_ASSERT(check == NULL);
   532         CX_TEST_ASSERT(end == check_last);
   533     }
   534     destroy_nodes_test_data(begin);
   535     free(sorted);
   536     free(testdata);
   537 }
   539 CX_TEST(test_linked_list_reverse) {
   540     void *testdata = create_nodes_test_data(4);
   541     void *expected = create_nodes_test_data(4);
   542     assign_nodes_test_data(testdata, 2, 4, 6, 8);
   543     assign_nodes_test_data(expected, 8, 6, 4, 2);
   544     void *begin = testdata;
   545     CX_TEST_DO {
   546         void *end = cx_linked_list_last(begin, loc_next);
   547         void *orig_begin = begin, *orig_end = end;
   549         cx_linked_list_reverse(&begin, &end, loc_prev, loc_next);
   550         CX_TEST_ASSERT(end == orig_begin);
   551         CX_TEST_ASSERT(begin == orig_end);
   552         CX_TEST_ASSERT(0 == cx_linked_list_compare(begin, expected, loc_next, loc_data, cx_cmp_int));
   553     }
   554     destroy_nodes_test_data(begin);
   555     destroy_nodes_test_data(expected);
   556 }
   559 CX_TEST(test_empty_list_size) {
   560     CX_TEST_DO {
   561         CX_TEST_ASSERT(cxEmptyList->size == 0);
   562         CX_TEST_ASSERT(cxListSize(cxEmptyList) == 0);
   563     }
   564 }
   566 CX_TEST(test_empty_list_iterator) {
   567     CxList *list = cxEmptyList;
   569     CxIterator it1 = cxListIterator(list);
   570     CxIterator it2 = cxListBackwardsIterator(list);
   571     CxMutIterator it3 = cxListMutIterator(list);
   572     CxMutIterator it4 = cxListMutBackwardsIterator(list);
   574     CX_TEST_DO {
   575         CX_TEST_ASSERT(!cxIteratorValid(it1));
   576         CX_TEST_ASSERT(!cxIteratorValid(it2));
   577         CX_TEST_ASSERT(!cxIteratorValid(it3));
   578         CX_TEST_ASSERT(!cxIteratorValid(it4));
   580         int c = 0;
   581         cx_foreach(void*, data, it1) c++;
   582         cx_foreach(void*, data, it2) c++;
   583         cx_foreach(void*, data, it3) c++;
   584         cx_foreach(void*, data, it4) c++;
   585         CX_TEST_ASSERT(c == 0);
   586     }
   587 }
   589 CX_TEST(test_empty_list_noops) {
   590     CX_TEST_DO {
   591         CxList copy = *cxEmptyList;
   592         cxListSort(cxEmptyList);
   593         cxListClear(cxEmptyList);
   594         cxListDestroy(cxEmptyList);
   595         CX_TEST_ASSERT(0 == memcmp(&copy, cxEmptyList, sizeof(CxList))); // NOLINT(*-suspicious-memory-comparison)
   596     }
   597 }
   599 CX_TEST(test_empty_list_at) {
   600     CX_TEST_DO {
   601         CX_TEST_ASSERT(cxListAt(cxEmptyList, 0) == NULL);
   602         CX_TEST_ASSERT(cxListAt(cxEmptyList, 1) == NULL);
   603     }
   604 }
   606 CX_TEST(test_empty_list_find) {
   607     int x = 42, y = 1337;
   608     CX_TEST_DO {
   609         CX_TEST_ASSERT(cxListFind(cxEmptyList, &x) < 0);
   610         CX_TEST_ASSERT(cxListFind(cxEmptyList, &y) < 0);
   611     }
   612 }
   614 CX_TEST(test_empty_list_compare) {
   615     CxList *empty = cxEmptyList;
   616     CxList *ll = cxLinkedListCreateSimple(sizeof(int));
   617     CxList *al = cxArrayListCreateSimple(sizeof(int), 8);
   618     int x = 5;
   619     CX_TEST_DO {
   620         CX_TEST_ASSERT(0 == cxListCompare(empty, cxEmptyList));
   621         CX_TEST_ASSERT(0 == cxListCompare(ll, cxEmptyList));
   622         CX_TEST_ASSERT(0 == cxListCompare(al, cxEmptyList));
   623         CX_TEST_ASSERT(0 == cxListCompare(cxEmptyList, ll));
   624         CX_TEST_ASSERT(0 == cxListCompare(cxEmptyList, al));
   626         cxListAdd(ll, &x);
   627         cxListAdd(al, &x);
   629         CX_TEST_ASSERT(0 < cxListCompare(ll, cxEmptyList));
   630         CX_TEST_ASSERT(0 < cxListCompare(al, cxEmptyList));
   631         CX_TEST_ASSERT(0 > cxListCompare(cxEmptyList, ll));
   632         CX_TEST_ASSERT(0 > cxListCompare(cxEmptyList, al));
   633     }
   634     cxListDestroy(ll);
   635     cxListDestroy(al);
   636 }
   638 CxTestSuite *cx_test_suite_array_list(void) {
   639     CxTestSuite *suite = cx_test_suite_new("array_list");
   641     return suite;
   642 }
   644 CxTestSuite *cx_test_suite_linked_list(void) {
   645     CxTestSuite *suite = cx_test_suite_new("linked_list");
   647     cx_test_register(suite, test_linked_list_link_unlink);
   648     cx_test_register(suite, test_linked_list_at);
   649     cx_test_register(suite, test_linked_list_find);
   650     cx_test_register(suite, test_linked_list_compare);
   651     cx_test_register(suite, test_linked_list_add);
   652     cx_test_register(suite, test_linked_list_prepend);
   653     cx_test_register(suite, test_linked_list_insert);
   654     cx_test_register(suite, test_linked_list_insert_chain);
   655     cx_test_register(suite, test_linked_list_first);
   656     cx_test_register(suite, test_linked_list_last);
   657     cx_test_register(suite, test_linked_list_prev);
   658     cx_test_register(suite, test_linked_list_remove);
   659     cx_test_register(suite, test_linked_list_size);
   660     cx_test_register(suite, test_linked_list_sort_empty);
   661     cx_test_register(suite, test_linked_list_sort);
   662     cx_test_register(suite, test_linked_list_reverse);
   664     return suite;
   665 }
   667 CxTestSuite *cx_test_suite_empty_list(void) {
   668     CxTestSuite *suite = cx_test_suite_new("empty list dummy");
   670     cx_test_register(suite, test_empty_list_size);
   671     cx_test_register(suite, test_empty_list_iterator);
   672     cx_test_register(suite, test_empty_list_noops);
   673     cx_test_register(suite, test_empty_list_at);
   674     cx_test_register(suite, test_empty_list_find);
   675     cx_test_register(suite, test_empty_list_compare);
   677     return suite;
   678 }

mercurial