Sat, 09 Apr 2022 18:02:53 +0200
#129 - remove test code duplication
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "cx/linked_list.h" #include "cx/utils.h" #include "test_config.h" #include "util_allocator.h" static int cmp_int_impl( int const *l, int const *r ) { int left = *l, right = *r; return left == right ? 0 : (left < right ? -1 : 1); } #define cmp_int ((CxListComparator) cmp_int_impl) struct node { struct node *next; struct node *prev; int data; }; #define nd(name) name = {0} const ptrdiff_t loc_prev = offsetof(struct node, prev); const ptrdiff_t loc_next = offsetof(struct node, next); const ptrdiff_t loc_data = offsetof(struct node, data); static struct node *create_nodes_test_data( size_t n, int const data[] ) { CU_ASSERT_NOT_EQUAL_FATAL(n, 0) struct node *begin = calloc(1, sizeof(struct node)); struct node *prev = begin; if (data) begin->data = data[0]; for (size_t i = 1; i < n; i++) { struct node *node = calloc(1, sizeof(struct node)); if (data) node->data = data[i]; cx_linked_list_link(prev, node, loc_prev, loc_next); prev = node; } return begin; } static void destroy_nodes_test_data(struct node *begin) { struct node *node = begin; while (node) { struct node *next = node->next; free(node); node = next; } } static int *create_ints_test_data(size_t len) { int *data = malloc(sizeof(int) * len); cx_for_n (i, len) data[i] = rand(); // NOLINT(cert-msc50-cpp) return data; } void test_linked_list_link_unlink(void) { struct node nd(a), nd(b), nd(c); cx_linked_list_link(&a, &b, loc_prev, loc_next); CU_ASSERT_PTR_NULL(a.prev) CU_ASSERT_PTR_EQUAL(a.next, &b) CU_ASSERT_PTR_EQUAL(b.prev, &a) CU_ASSERT_PTR_NULL(b.next) cx_linked_list_unlink(&a, &b, loc_prev, loc_next); CU_ASSERT_PTR_NULL(a.prev) CU_ASSERT_PTR_NULL(a.next) CU_ASSERT_PTR_NULL(b.prev) CU_ASSERT_PTR_NULL(b.next) cx_linked_list_link(&b, &c, loc_prev, loc_next); cx_linked_list_link(&a, &b, loc_prev, loc_next); cx_linked_list_unlink(&b, &c, loc_prev, loc_next); CU_ASSERT_PTR_NULL(a.prev) CU_ASSERT_PTR_EQUAL(a.next, &b) CU_ASSERT_PTR_EQUAL(b.prev, &a) CU_ASSERT_PTR_NULL(b.next) CU_ASSERT_PTR_NULL(c.prev) CU_ASSERT_PTR_NULL(c.next) } void test_linked_list_at(void) { struct node nd(a), nd(b), nd(c), nd(d); cx_linked_list_link(&a, &b, loc_prev, loc_next); cx_linked_list_link(&b, &c, loc_prev, loc_next); cx_linked_list_link(&c, &d, loc_prev, loc_next); CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 0), &a) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 1), &b) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 2), &c) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 3), &d) CU_ASSERT_PTR_NULL(cx_linked_list_at(&a, 0, loc_next, 4)) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_prev, 0), &a) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 1), &b) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 2), &c) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 3), &d) CU_ASSERT_PTR_NULL(cx_linked_list_at(&b, 1, loc_next, 4)) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 0), &a) CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 1), &b) } void test_linked_list_find(void) { int data[] = {2, 4, 6, 8}; void *list = create_nodes_test_data(4, data); int s; s = 2; CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, false, cmp_int, &s), 0) s = 4; CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, false, cmp_int, &s), 1) s = 6; CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, false, cmp_int, &s), 2) s = 8; CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, false, cmp_int, &s), 3) s = 10; CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, false, cmp_int, &s), 4) s = -2; CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, false, cmp_int, &s), 4) } void test_linked_list_compare(void) { int a[] = {2, 4, 6, 8}; int b[] = {2, 4, 6}; int c[] = {2, 4, 6, 9}; void *la = create_nodes_test_data(4, a); void *lb = create_nodes_test_data(3, b); void *lc = create_nodes_test_data(4, c); CU_ASSERT_TRUE(0 < cx_linked_list_compare(la, lb, loc_next, loc_data, false, cmp_int) ) CU_ASSERT_TRUE(0 > cx_linked_list_compare(lb, la, loc_next, loc_data, false, cmp_int) ) CU_ASSERT_TRUE(0 < cx_linked_list_compare(lc, la, loc_next, loc_data, false, cmp_int) ) CU_ASSERT_TRUE(0 > cx_linked_list_compare(la, lc, loc_next, loc_data, false, cmp_int) ) CU_ASSERT_TRUE(0 == cx_linked_list_compare(la, la, loc_next, loc_data, false, cmp_int) ) destroy_nodes_test_data(la); destroy_nodes_test_data(lb); destroy_nodes_test_data(lc); } void test_linked_list_add(void) { struct node nodes[4]; void *begin, *end; // test with begin, end / prev, next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[0]) CU_ASSERT_PTR_NULL(nodes[0].prev) CU_ASSERT_PTR_NULL(nodes[0].next) cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) // test with begin only / prev, next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[2]); CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) // test with end only / prev, next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(end, &nodes[0]) cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(end, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[2]); CU_ASSERT_PTR_EQUAL(end, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) // test with begin, end / next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[0]) cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(end, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) CU_ASSERT_PTR_NULL(nodes[1].prev) } void test_linked_list_prepend(void) { struct node nodes[4]; void *begin, *end; // test with begin, end / prev, next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[0]) CU_ASSERT_PTR_NULL(nodes[0].prev) CU_ASSERT_PTR_NULL(nodes[0].next) cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(begin, &nodes[1]) CU_ASSERT_PTR_EQUAL(end, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) // test with begin only / prev, next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(begin, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[2]); CU_ASSERT_PTR_EQUAL(begin, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[2]) // test with end only / prev, next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(end, &nodes[0]) cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[1]); CU_ASSERT_PTR_EQUAL(end, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[2]); CU_ASSERT_PTR_EQUAL(end, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[2]) // test with begin, end / next memset(nodes, 0, 4 * sizeof(struct node)); begin = end = NULL; cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[0]) cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); CU_ASSERT_PTR_EQUAL(begin, &nodes[2]) CU_ASSERT_PTR_EQUAL(end, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) CU_ASSERT_PTR_NULL(nodes[1].prev) CU_ASSERT_PTR_NULL(nodes[0].prev) } void test_linked_list_insert(void) { struct node nodes[4]; void *begin, *end; // insert mid list memset(nodes, 0, 4 * sizeof(struct node)); begin = &nodes[0]; end = &nodes[2]; cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[3]) CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[3]) CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[3].next, &nodes[2]) // insert end memset(nodes, 0, 4 * sizeof(struct node)); begin = &nodes[0]; end = &nodes[2]; cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[3]) CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[3]) CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[2]) CU_ASSERT_PTR_NULL(nodes[3].next) // insert begin memset(nodes, 0, 4 * sizeof(struct node)); begin = &nodes[0]; end = &nodes[2]; cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); cx_linked_list_insert(&begin, &end, loc_prev, loc_next, NULL, &nodes[3]); CU_ASSERT_PTR_EQUAL(begin, &nodes[3]) CU_ASSERT_PTR_EQUAL(end, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[3]) CU_ASSERT_PTR_NULL(nodes[3].prev) CU_ASSERT_PTR_EQUAL(nodes[3].next, &nodes[0]) } void test_linked_list_insert_chain(void) { struct node nodes[5]; void *begin, *end; // insert mid list memset(nodes, 0, 5 * sizeof(struct node)); begin = &nodes[0]; end = &nodes[2]; cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], NULL); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[3]) CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[4]) CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[1]) CU_ASSERT_PTR_EQUAL(nodes[4].next, &nodes[2]) // insert end memset(nodes, 0, 5 * sizeof(struct node)); begin = &nodes[0]; end = &nodes[2]; cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], NULL); CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) CU_ASSERT_PTR_EQUAL(end, &nodes[4]) CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[3]) CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[2]) CU_ASSERT_PTR_NULL(nodes[4].next) // insert begin memset(nodes, 0, 5 * sizeof(struct node)); begin = &nodes[0]; end = &nodes[2]; cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, NULL, &nodes[3], NULL); CU_ASSERT_PTR_EQUAL(begin, &nodes[3]) CU_ASSERT_PTR_EQUAL(end, &nodes[2]) CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[4]) CU_ASSERT_PTR_NULL(nodes[3].prev) CU_ASSERT_PTR_EQUAL(nodes[4].next, &nodes[0]) } void test_linked_list_first(void) { struct node *begin = create_nodes_test_data(3, NULL); CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin, loc_prev), begin) CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next, loc_prev), begin) CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next->next, loc_prev), begin) destroy_nodes_test_data(begin); } void test_linked_list_last(void) { struct node *begin = create_nodes_test_data(3, NULL); struct node *end = begin->next->next; CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin, loc_next), end) CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next, loc_next), end) CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next->next, loc_next), end) destroy_nodes_test_data(begin); } void test_linked_list_prev(void) { struct node *begin = create_nodes_test_data(3, NULL); CU_ASSERT_PTR_NULL(cx_linked_list_prev(begin, loc_next, begin)) CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next), begin) CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next) destroy_nodes_test_data(begin); } void test_linked_list_remove(void) { void *begin, *end; int data[] = {2, 4, 6}; begin = create_nodes_test_data(3, data); struct node *first = begin; struct node *second = first->next; struct node *third = second->next; end = third; cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); CU_ASSERT_PTR_EQUAL(begin, first) CU_ASSERT_PTR_EQUAL(end, third) CU_ASSERT_PTR_NULL(first->prev) CU_ASSERT_PTR_EQUAL(first->next, third) CU_ASSERT_PTR_EQUAL(third->prev, first) CU_ASSERT_PTR_NULL(third->next) cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); CU_ASSERT_PTR_EQUAL(begin, first) CU_ASSERT_PTR_EQUAL(end, first) CU_ASSERT_PTR_NULL(first->prev) CU_ASSERT_PTR_NULL(first->next) cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); CU_ASSERT_PTR_NULL(begin) CU_ASSERT_PTR_NULL(end) free(first); free(second); free(third); } void test_linked_list_size(void) { struct node *list; CU_ASSERT_PTR_EQUAL(cx_linked_list_size(NULL, loc_next), 0) list = create_nodes_test_data(5, NULL); CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 5) destroy_nodes_test_data(list); list = create_nodes_test_data(13, NULL); CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 13) destroy_nodes_test_data(list); } void test_linked_list_sort(void) { int expected[] = { 14, 30, 151, 163, 227, 300, 315, 317, 363, 398, 417, 424, 438, 446, 508, 555, 605, 713, 716, 759, 761, 880, 894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 1707, 1734, 1771, 1874, 1894, 1976, 2079, 2124, 2130, 2135, 2266, 2338, 2358, 2430, 2500, 2540, 2542, 2546, 2711, 2733, 2754, 2764, 2797, 2888, 2900, 3020, 3053, 3109, 3244, 3275, 3302, 3362, 3363, 3364, 3441, 3515, 3539, 3579, 3655, 3675, 3677, 3718, 3724, 3757, 3866, 3896, 3906, 3941, 3984, 3994, 4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681, 4785, 4791, 4801, 4859, 4903, 4973 }; int scrambled[] = { 759, 716, 880, 761, 2358, 2542, 2500, 2540, 2546, 2711, 2430, 1707, 1874, 1771, 1894, 1734, 1976, 2079, 2124, 2130, 2135, 2266, 2338, 2733, 2754, 2764, 2797, 3362, 3363, 3364, 3441, 3515, 3539, 3579, 3655, 2888, 2900, 3020, 3053, 3109, 3244, 3275, 3302, 438, 446, 508, 555, 605, 713, 14, 30, 151, 163, 227, 300, 894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 315, 317, 363, 398, 417, 424, 3675, 3677, 3718, 3724, 3757, 3866, 3896, 3906, 3941, 3984, 3994, 4785, 4791, 4801, 4859, 4903, 4973, 4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681 }; void *begin = create_nodes_test_data(100, scrambled); void *end = cx_linked_list_last(begin, loc_next); cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, false, cmp_int); struct node *check = begin; struct node *check_last = NULL; CU_ASSERT_PTR_NULL(check->prev) CU_ASSERT_EQUAL(check->data, expected[0]) cx_for_n (i, 100) { CU_ASSERT_EQUAL(check->data, expected[i]) CU_ASSERT_PTR_EQUAL(check->prev, check_last) if (i < 99) { CU_ASSERT_PTR_NOT_NULL(check->next) } check_last = check; check = check->next; } CU_ASSERT_PTR_NULL(check) CU_ASSERT_PTR_EQUAL(end, check_last) destroy_nodes_test_data(begin); } void test_linked_list_reverse(void) { void *begin, *end; int data[] = {2, 4, 6, 8}; int reversed[] = {8, 6, 4, 2}; void *list = create_nodes_test_data(4, data); void *expected = create_nodes_test_data(4, reversed); begin = list; end = cx_linked_list_last(list, loc_next); cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); CU_ASSERT_PTR_EQUAL(end, list) CU_ASSERT_PTR_EQUAL(begin, cx_linked_list_first(end, loc_prev)) CU_ASSERT_TRUE(0 == cx_linked_list_compare(begin, expected, loc_next, loc_data, 0, cmp_int)) destroy_nodes_test_data(begin); destroy_nodes_test_data(expected); } static void verify_linked_list_create(CxList *list) { CU_ASSERT_EQUAL(list->size, 0) CU_ASSERT_EQUAL(list->capacity, (size_t) -1) CU_ASSERT_PTR_EQUAL(list->allocator, cxTestingAllocator) CU_ASSERT_PTR_EQUAL(list->cmpfunc, cmp_int) cxListDestroy(list); } void test_hl_linked_list_create(void) { CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); CU_ASSERT_EQUAL(list->itemsize, sizeof(int)) verify_linked_list_create(list); } void test_hl_ptr_linked_list_create(void) { CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); CU_ASSERT_EQUAL(list->itemsize, sizeof(void *)) verify_linked_list_create(list); } void test_hl_linked_list_from_array(void) { int data[] = {2, 4, 5, 7, 10, 15}; CxList *expected = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); cx_for_n (i, 5) cxListAdd(expected, &data[i]); CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, data); CU_ASSERT_TRUE(0 == cxListCompare(list, expected)) cxListDestroy(list); cxListDestroy(expected); } static void verify_hl_linked_list_add( CxList *list, int data[], size_t len, bool write_through ) { cx_for_n (i, len) CU_ASSERT_EQUAL(cxListAdd(list, &data[i]), 0) CU_ASSERT_EQUAL(list->size, len) CU_ASSERT_TRUE(list->capacity >= list->size) cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) cx_for_n (i, len) ++data[i]; if (write_through) { cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) } else { cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i] - 1) } cxListDestroy(list); } void test_hl_linked_list_add(void) { CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); int data[] = {5, 47, 13, 9, 18, 1, 42}; verify_hl_linked_list_add(list, data, sizeof(data) / sizeof(int), false); } void test_hl_ptr_linked_list_add(void) { CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); int data[] = {5, 47, 84, 13, 9, 18, 90, 1, 42}; verify_hl_linked_list_add(list, data, sizeof(data) / sizeof(int), true); } static void verify_hl_linked_list_insert(CxList *list) { int a = 5, b = 47, c = 13, d = 42; CU_ASSERT_NOT_EQUAL(cxListInsert(list, 1, &a), 0) CU_ASSERT_EQUAL(list->size, 0) CU_ASSERT_EQUAL(cxListInsert(list, 0, &a), 0) CU_ASSERT_EQUAL(list->size, 1) CU_ASSERT_EQUAL(cxListInsert(list, 0, &b), 0) CU_ASSERT_EQUAL(list->size, 2) CU_ASSERT_EQUAL(cxListInsert(list, 1, &c), 0) CU_ASSERT_EQUAL(list->size, 3) CU_ASSERT_EQUAL(cxListInsert(list, 3, &d), 0) CU_ASSERT_EQUAL(list->size, 4) CU_ASSERT_TRUE(list->capacity >= list->size) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 13) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 5) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 3), 42) cxListDestroy(list); } void test_hl_linked_list_insert(void) { verify_hl_linked_list_insert(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int))); } void test_hl_ptr_linked_list_insert(void) { verify_hl_linked_list_insert(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); } static void verify_hl_linked_list_remove(CxList *list) { CU_ASSERT_EQUAL(list->size, 4) CU_ASSERT_TRUE(list->capacity >= list->size) CU_ASSERT_NOT_EQUAL(cxListRemove(list, 4), 0) CU_ASSERT_EQUAL(cxListRemove(list, 2), 0) CU_ASSERT_EQUAL(list->size, 3) CU_ASSERT_TRUE(list->capacity >= list->size) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 5) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 47) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 13) CU_ASSERT_EQUAL(cxListRemove(list, 0), 0) CU_ASSERT_EQUAL(list->size, 2) CU_ASSERT_TRUE(list->capacity >= list->size) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 13) CU_ASSERT_EQUAL(cxListRemove(list, 1), 0) CU_ASSERT_EQUAL(list->size, 1) CU_ASSERT_TRUE(list->capacity >= list->size) CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) CU_ASSERT_EQUAL(cxListRemove(list, 0), 0) CU_ASSERT_EQUAL(list->size, 0) CU_ASSERT_TRUE(list->capacity >= list->size) CU_ASSERT_NOT_EQUAL(cxListRemove(list, 0), 0) cxListDestroy(list); } void test_hl_linked_list_remove(void) { int data[] = {5, 47, 42, 13}; CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 4, data); verify_hl_linked_list_remove(list); } void test_hl_ptr_linked_list_remove(void) { int a = 5, b = 47, c = 42, d = 13; CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); cxListAdd(list, &a); cxListAdd(list, &b); cxListAdd(list, &c); cxListAdd(list, &d); verify_hl_linked_list_remove(list); } static void verify_hl_linked_list_at( CxList *list, size_t len, int *data ) { CU_ASSERT_EQUAL(list->size, len) cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) CU_ASSERT_PTR_NULL(cxListAt(list, len)) free(data); cxListDestroy(list); } void test_hl_linked_list_at(void) { size_t len = 100; int *data = create_ints_test_data(len); CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), len, data); verify_hl_linked_list_at(list, len, data); } void test_hl_ptr_linked_list_at(void) { size_t len = 250; int *data = create_ints_test_data(len); CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); cx_for_n (i, len) cxListAdd(list, &data[i]); verify_hl_linked_list_at(list, len, data); } static void verify_hl_linked_list_find( CxList *list, size_t len, int *data ) { cx_for_n (attempt, 100) { size_t exp = rand() % len; // NOLINT(cert-msc50-cpp) int val = data[exp]; cx_for_n (i, exp) { if (data[i] == val) { exp = i; break; } } CU_ASSERT_EQUAL(cxListFind(list, &val), exp) } free(data); cxListDestroy(list); } void test_hl_linked_list_find(void) { size_t len = 100; int *data = create_ints_test_data(len); CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), len, data); verify_hl_linked_list_find(list, len, data); } void test_hl_ptr_linked_list_find(void) { size_t len = 250; int *data = create_ints_test_data(len); CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); cx_for_n (i, len) cxListAdd(list, &data[i]); verify_hl_linked_list_find(list, len, data); } struct sort_test_data { size_t len; int *data; int *sorted; }; static struct sort_test_data create_sort_test_data(void) { size_t len = 1000; int *data = create_ints_test_data(len); int *sorted = malloc(sizeof(int) * len); memcpy(sorted, data, sizeof(int) * len); qsort(sorted, len, sizeof(int), cmp_int); struct sort_test_data s = {len, data, sorted}; return s; } static void free_sort_test_data(struct sort_test_data s) { free(s.data); free(s.sorted); } static void verify_hl_linked_list_sort( CxList *list, struct sort_test_data td ) { cxListSort(list); cx_for_n (i, td.len) CU_ASSERT_EQUAL_FATAL(*(int *) cxListAt(list, i), td.sorted[i]) free_sort_test_data(td); cxListDestroy(list); } void test_hl_linked_list_sort(void) { struct sort_test_data td = create_sort_test_data(); CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), td.len, td.data); verify_hl_linked_list_sort(list, td); } void test_hl_ptr_linked_list_sort(void) { struct sort_test_data td = create_sort_test_data(); CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); cx_for_n (i, td.len) cxListAdd(list, &td.data[i]); verify_hl_linked_list_sort(list, td); } void verify_hl_linked_list_iterator(CxList *list) { int i = 0; CxIterator iter = cxListBegin(list); cx_foreach(int*, x, iter) { CU_ASSERT_EQUAL(iter.index, (size_t) (i + 1) / 2) CU_ASSERT_EQUAL(*x, i) if (*x % 2 == 1) iter.remove = true; i++; } CU_ASSERT_EQUAL(i, 10) CU_ASSERT_EQUAL_FATAL(list->size, 5) cx_for_n(j, 5) CU_ASSERT_EQUAL(*(int *) cxListAt(list, j), (int) j * 2) cxListDestroy(list); } void test_hl_linked_list_iterator(void) { CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); cx_for_n (i, 10) cxListAdd(list, &i); verify_hl_linked_list_iterator(list); } void test_hl_ptr_linked_list_iterator(void) { CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; cx_for_n (i, 10) cxListAdd(list, &data[i]); verify_hl_linked_list_iterator(list); } static void verify_hl_linked_list_insert_via_iterator( CxList *list, int *testdata ) { CxIterator iter = cxListIterator(list, 2); CU_ASSERT_EQUAL(iter.index, 2) CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) size_t i = 4; ++i; cxListInsertAfter(&iter, &testdata[i]); CU_ASSERT_EQUAL(iter.index, 2) CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) ++i; cxListInsertBefore(&iter, &testdata[i]); CU_ASSERT_EQUAL(iter.index, 3) CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) iter = cxListBegin(list); ++i; cxListInsertBefore(&iter, &testdata[i]); CU_ASSERT_EQUAL(iter.index, 1) CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 0) iter = cxListIterator(list, list->size); ++i; cxListInsertBefore(&iter, &testdata[i]); CU_ASSERT_EQUAL(iter.index, 9) CU_ASSERT_FALSE(cxIteratorValid(&iter)) iter = cxListIterator(list, list->size); ++i; cxListInsertAfter(&iter, &testdata[i]); CU_ASSERT_EQUAL(iter.index, 10) CU_ASSERT_FALSE(cxIteratorValid(&iter)) int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; cx_for_n (j, 10) CU_ASSERT_EQUAL(*(int *) cxListAt(list, j), expdata[j]) cxListDestroy(list); } void test_hl_linked_list_insert_via_iterator(void) { int testdata[] = {0, 1, 2, 3, 4, 10, 20, 30, 40, 50}; // only add the first five elements, the remaining five will be inserted CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, testdata); verify_hl_linked_list_insert_via_iterator(list, testdata); } void test_hl_ptr_linked_list_insert_via_iterator(void) { int testdata[] = {0, 1, 2, 3, 4, 10, 20, 30, 40, 50}; CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); // only add the first five elements, the remaining five will be inserted cx_for_n (i, 5) cxListAdd(list, &testdata[i]); verify_hl_linked_list_insert_via_iterator(list, testdata); } static void test_setup_allocator(void) { cxTestingAllocatorReset(); } static void test_verify_allocator(void) { CU_ASSERT_TRUE(cxTestingAllocatorVerify()) } int main() { CU_pSuite suite = NULL; if (CUE_SUCCESS != CU_initialize_registry()) { return CU_get_error(); } suite = CU_add_suite("low level linked list", NULL, NULL); cu_add_test(suite, test_linked_list_link_unlink); cu_add_test(suite, test_linked_list_at); cu_add_test(suite, test_linked_list_find); cu_add_test(suite, test_linked_list_compare); cu_add_test(suite, test_linked_list_prepend); cu_add_test(suite, test_linked_list_add); cu_add_test(suite, test_linked_list_insert); cu_add_test(suite, test_linked_list_insert_chain); cu_add_test(suite, test_linked_list_first); cu_add_test(suite, test_linked_list_last); cu_add_test(suite, test_linked_list_prev); cu_add_test(suite, test_linked_list_remove); cu_add_test(suite, test_linked_list_size); cu_add_test(suite, test_linked_list_sort); cu_add_test(suite, test_linked_list_reverse); suite = CU_add_suite_with_setup_and_teardown( "high level linked list", NULL, NULL, test_setup_allocator, test_verify_allocator); cu_add_test(suite, test_hl_linked_list_create); cu_add_test(suite, test_hl_linked_list_from_array); cu_add_test(suite, test_hl_linked_list_add); cu_add_test(suite, test_hl_linked_list_insert); cu_add_test(suite, test_hl_linked_list_remove); cu_add_test(suite, test_hl_linked_list_at); cu_add_test(suite, test_hl_linked_list_find); cu_add_test(suite, test_hl_linked_list_sort); cu_add_test(suite, test_hl_linked_list_iterator); cu_add_test(suite, test_hl_linked_list_insert_via_iterator); suite = CU_add_suite_with_setup_and_teardown( "high level pointer linked list", NULL, NULL, test_setup_allocator, test_verify_allocator); cu_add_test(suite, test_hl_ptr_linked_list_create); cu_add_test(suite, test_hl_ptr_linked_list_add); cu_add_test(suite, test_hl_ptr_linked_list_insert); cu_add_test(suite, test_hl_ptr_linked_list_remove); cu_add_test(suite, test_hl_ptr_linked_list_at); cu_add_test(suite, test_hl_ptr_linked_list_find); cu_add_test(suite, test_hl_ptr_linked_list_sort); cu_add_test(suite, test_hl_ptr_linked_list_iterator); cu_add_test(suite, test_hl_ptr_linked_list_insert_via_iterator); CU_basic_set_mode(UCX_CU_BRM); int exitcode; if (CU_basic_run_tests()) { exitcode = CU_get_error(); } else { exitcode = CU_get_number_of_failures() == 0 ? 0 : 1; } CU_cleanup_registry(); return exitcode; }