tests/test_list.c

changeset 1419
e46406fd1b3c
parent 1388
edc34e904fe3
--- a/tests/test_list.c	Fri Oct 10 12:26:43 2025 +0200
+++ b/tests/test_list.c	Fri Oct 10 17:24:19 2025 +0200
@@ -171,9 +171,11 @@
     int d6a[6] = {52, 54, 56, 62, 64, 75};
     int d7a[6] = {51, 57, 58, 65, 77, 78};
     int d8 = 90;
-    int expected[18] = {
-            40, 50, 51, 52, 54, 56, 57, 58, 60,
-            62, 64, 65, 70, 75, 77, 78, 80, 90
+    int d9 = 56;
+    int d10a[3] = {67, 75, 90};
+    int expected[22] = {
+            40, 50, 51, 52, 54, 56, 56, 57, 58, 60,
+            62, 64, 65, 67, 70, 75, 75, 77, 78, 80, 90, 90
     };
 
     CX_ARRAY_DECLARE(int, array);
@@ -204,8 +206,70 @@
         CX_TEST_ASSERT(0 == cx_array_simple_add_sorted(array, d8, cx_cmp_int));
         CX_TEST_ASSERT(array_size == 18);
         CX_TEST_ASSERT(array_capacity >= 18);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_sorted(array, d9, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 19);
+        CX_TEST_ASSERT(array_capacity >= 19);
+        CX_TEST_ASSERT(0 == cx_array_simple_insert_sorted(array, d10a, 3, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 22);
+        CX_TEST_ASSERT(array_capacity >= 22);
 
-        CX_TEST_ASSERT(0 == memcmp(array, expected, 18 * sizeof(int)));
+        CX_TEST_ASSERT(0 == memcmp(array, expected, 22 * sizeof(int)));
+    }
+    cxFreeDefault(array);
+}
+
+CX_TEST(test_array_insert_unique) {
+    int d1 = 50;
+    int d2 = 80;
+    int d3 = 60;
+    int d4 = 40;
+    int d5 = 70;
+    int d6a[6] = {52, 54, 56, 62, 64, 75};
+    int d7a[6] = {51, 57, 58, 65, 77, 78};
+    int d8 = 90;
+    int d9 = 56;
+    int d10a[3] = {67, 75, 90};
+    int expected[19] = {
+            40, 50, 51, 52, 54, 56, 57, 58, 60,
+            62, 64, 65, 67, 70, 75, 77, 78, 80, 90
+    };
+
+    CX_ARRAY_DECLARE(int, array);
+    cx_array_initialize(array, 4);
+
+    CX_TEST_DO {
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d1, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 1);
+        CX_TEST_ASSERT(array_capacity == 4);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d2, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 2);
+        CX_TEST_ASSERT(array_capacity == 4);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d3, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 3);
+        CX_TEST_ASSERT(array_capacity == 4);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d4, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 4);
+        CX_TEST_ASSERT(array_capacity == 4);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d5, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 5);
+        CX_TEST_ASSERT(array_capacity >= 5);
+        CX_TEST_ASSERT(0 == cx_array_simple_insert_unique(array, d6a, 6, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 11);
+        CX_TEST_ASSERT(array_capacity >= 11);
+        CX_TEST_ASSERT(0 == cx_array_simple_insert_unique(array, d7a, 6, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 17);
+        CX_TEST_ASSERT(array_capacity >= 17);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d8, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 18);
+        CX_TEST_ASSERT(array_capacity >= 18);
+        CX_TEST_ASSERT(0 == cx_array_simple_add_unique(array, d9, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 18);
+        CX_TEST_ASSERT(array_capacity >= 18);
+        CX_TEST_ASSERT(0 == cx_array_simple_insert_unique(array, d10a, 3, cx_cmp_int));
+        CX_TEST_ASSERT(array_size == 19);
+        CX_TEST_ASSERT(array_capacity >= 19);
+
+        CX_TEST_ASSERT(0 == memcmp(array, expected, 19 * sizeof(int)));
     }
     cxFreeDefault(array);
 }
@@ -737,6 +801,121 @@
     }
 }
 
+CX_TEST(test_linked_list_insert_unique) {
+    node nodes[5] = {0};
+    void *begin, *end;
+    nodes[0].data = 3;
+    nodes[1].data = 6;
+    nodes[2].data = 10;
+    nodes[3].data = 11;
+    nodes[4].data = 15;
+    for (unsigned i = 0 ; i < 4 ; i++) {
+        cx_linked_list_link(&nodes[i], &nodes[i+1], loc_prev, loc_next);
+    }
+    begin = &nodes[0];
+    end = &nodes[4];
+    CX_TEST_DO {
+        // insert a single node
+        node new_node = {0};
+        new_node.data = 5;
+        CX_TEST_ASSERT(0 == cx_linked_list_insert_unique(
+                &begin, &end,
+                loc_prev, loc_next,
+                &new_node, test_cmp_node
+        ));
+        CX_TEST_ASSERT(new_node.prev == &nodes[0]);
+        CX_TEST_ASSERT(new_node.next == &nodes[1]);
+        CX_TEST_ASSERT(nodes[0].next == &new_node);
+        CX_TEST_ASSERT(nodes[1].prev == &new_node);
+        CX_TEST_ASSERT(begin == &nodes[0]);
+        CX_TEST_ASSERT(end == &nodes[4]);
+
+        // now as duplicate
+        node new_node_dup = {0};
+        new_node_dup.data = 5;
+        CX_TEST_ASSERT(0 != cx_linked_list_insert_unique(
+                &begin, &end,
+                loc_prev, loc_next,
+                &new_node_dup, test_cmp_node
+        ));
+        CX_TEST_ASSERT(new_node_dup.prev == NULL);
+        CX_TEST_ASSERT(new_node_dup.next == NULL);
+        CX_TEST_ASSERT(new_node.prev == &nodes[0]);
+        CX_TEST_ASSERT(new_node.next == &nodes[1]);
+        CX_TEST_ASSERT(nodes[0].next == &new_node);
+        CX_TEST_ASSERT(nodes[1].prev == &new_node);
+        CX_TEST_ASSERT(begin == &nodes[0]);
+        CX_TEST_ASSERT(end == &nodes[4]);
+
+        // insert a new beginning node
+        node new_begin = {0};
+        new_begin.data = 1;
+        CX_TEST_ASSERT(0 == cx_linked_list_insert_unique(
+                &begin, &end,
+                loc_prev, loc_next,
+                &new_begin, test_cmp_node
+        ));
+        CX_TEST_ASSERT(new_begin.prev == NULL);
+        CX_TEST_ASSERT(new_begin.next == &nodes[0]);
+        CX_TEST_ASSERT(nodes[0].prev == &new_begin);
+        CX_TEST_ASSERT(begin == &new_begin);
+        CX_TEST_ASSERT(end == &nodes[4]);
+
+        // now as duplicate
+        node new_begin_dup = {0};
+        new_begin_dup.data = 1;
+        CX_TEST_ASSERT(0 != cx_linked_list_insert_unique(
+                &begin, &end,
+                loc_prev, loc_next,
+                &new_begin_dup, test_cmp_node
+        ));
+        CX_TEST_ASSERT(new_begin_dup.prev == NULL);
+        CX_TEST_ASSERT(new_begin_dup.next == NULL);
+        CX_TEST_ASSERT(new_begin.prev == NULL);
+        CX_TEST_ASSERT(new_begin.next == &nodes[0]);
+        CX_TEST_ASSERT(nodes[0].prev == &new_begin);
+        CX_TEST_ASSERT(begin == &new_begin);
+        CX_TEST_ASSERT(end == &nodes[4]);
+
+        // now insert a chain with two duplicates
+        node chain_start  = {NULL, NULL, 8};
+        node chain_mid1 = {NULL, NULL, 11};
+        node chain_mid2 = {NULL, NULL, 14};
+        node chain_mid3 = {NULL, NULL, 15};
+        node chain_mid4 = {NULL, NULL, 15};
+        node chain_end = {NULL, NULL, 17};
+        cx_linked_list_link(&chain_start, &chain_mid1, loc_prev, loc_next);
+        cx_linked_list_link(&chain_mid1, &chain_mid2, loc_prev, loc_next);
+        cx_linked_list_link(&chain_mid2, &chain_mid3, loc_prev, loc_next);
+        cx_linked_list_link(&chain_mid3, &chain_mid4, loc_prev, loc_next);
+        cx_linked_list_link(&chain_mid4, &chain_end, loc_prev, loc_next);
+
+        node *dup_start = cx_linked_list_insert_unique_chain(
+                &begin, &end,
+                loc_prev, loc_next,
+                &chain_start, test_cmp_node
+        );
+
+        CX_TEST_ASSERT(chain_start.prev == &nodes[1]);
+        CX_TEST_ASSERT(chain_start.next == &nodes[2]);
+        CX_TEST_ASSERT(chain_mid2.prev == &nodes[3]);
+        CX_TEST_ASSERT(chain_mid2.next == &nodes[4]);
+        CX_TEST_ASSERT(chain_end.prev == &nodes[4]);
+        CX_TEST_ASSERT(chain_end.next == NULL);
+        CX_TEST_ASSERT(begin == &new_begin);
+        CX_TEST_ASSERT(end == &chain_end);
+
+        // the duplicates
+        CX_TEST_ASSERT(dup_start == &chain_mid1);
+        CX_TEST_ASSERT(dup_start->prev == NULL);
+        CX_TEST_ASSERT(dup_start->next == &chain_mid3);
+        CX_TEST_ASSERT(chain_mid3.prev == &chain_mid1);
+        CX_TEST_ASSERT(chain_mid3.next == &chain_mid4);
+        CX_TEST_ASSERT(chain_mid4.prev == &chain_mid3);
+        CX_TEST_ASSERT(chain_mid4.next == NULL);
+    }
+}
+
 CX_TEST(test_linked_list_first) {
     node *testdata = create_nodes_test_data(3);
     void *begin = testdata;
@@ -1299,6 +1478,7 @@
     const cx_list_class *cl = list->climpl == NULL ? list->cl : list->climpl;
     memcpy(defaulted_cl, cl, sizeof(cx_list_class));
     defaulted_cl->insert_array = cx_list_default_insert_array;
+    defaulted_cl->insert_unique = cx_list_default_insert_unique;
     defaulted_cl->insert_sorted = cx_list_default_insert_sorted;
     defaulted_cl->sort = cx_list_default_sort;
     defaulted_cl->swap = cx_list_default_swap;
@@ -1513,16 +1693,22 @@
     int d6a[6] = array_init(52, 54, 56, 62, 64, 75);
     int d7a[6] = array_init(51, 57, 58, 65, 77, 78);
     int d8 = 90;
+    int d9 = 56;
+    int d10a[3] = array_init(67, 75, 90);
     int *d6ptr[6];
     int *d7ptr[6];
+    int *d10ptr[3];
     for (size_t i = 0; i < 6; i++) {
         d6ptr[i] = &d6a[i];
         d7ptr[i] = &d7a[i];
     }
+    for (size_t i = 0 ; i < 3 ; i++) {
+        d10ptr[i] = &d10a[i];
+    }
     size_t inserted;
-    int expected[18] = array_init(
-            40, 50, 51, 52, 54, 56, 57, 58, 60,
-            62, 64, 65, 70, 75, 77, 78, 80, 90
+    int expected[22] = array_init(
+        40, 50, 51, 52, 54, 56, 56, 57, 58, 60,
+        62, 64, 65, 67, 70, 75, 75, 77, 78, 80, 90, 90
     );
 
     CX_TEST_ASSERT(0 == cxListInsertSorted(list, &d1));
@@ -1543,9 +1729,73 @@
     }
     CX_TEST_ASSERT(inserted == 6);
     CX_TEST_ASSERT(0 == cxListInsertSorted(list, &d8));
+    CX_TEST_ASSERT(0 == cxListInsertSorted(list, &d9));
+    if (isptrlist) {
+        inserted = cxListInsertSortedArray(list, d10ptr, 3);
+    } else {
+        inserted = cxListInsertSortedArray(list, d10a, 3);
+    }
+    CX_TEST_ASSERT(inserted == 3);
+    CX_TEST_ASSERT(cxListSize(list) == 22);
+    for (size_t i = 0; i < 22; i++) {
+        CX_TEST_ASSERT(*(int *) cxListAt(list, i) == expected[i]);
+    }
+})
 
-    CX_TEST_ASSERT(cxListSize(list) == 18);
-    for (size_t i = 0; i < 18; i++) {
+roll_out_test_combos_with_defaulted_funcs(insert_unique, {
+    int d1 = 50;
+    int d2 = 80;
+    int d3 = 60;
+    int d4 = 40;
+    int d5 = 70;
+    int d6a[6] = array_init(52, 54, 56, 62, 64, 75);
+    int d7a[6] = array_init(51, 57, 58, 65, 77, 78);
+    int d8 = 90;
+    int d9 = 56;
+    int d10a[3] = array_init(67, 75, 90);
+    int *d6ptr[6];
+    int *d7ptr[6];
+    int *d10ptr[3];
+    for (size_t i = 0; i < 6; i++) {
+        d6ptr[i] = &d6a[i];
+        d7ptr[i] = &d7a[i];
+    }
+    for (size_t i = 0 ; i < 3 ; i++) {
+        d10ptr[i] = &d10a[i];
+    }
+    size_t inserted;
+    int expected[19] = array_init(
+        40, 50, 51, 52, 54, 56, 57, 58, 60,
+        62, 64, 65, 67, 70, 75, 77, 78, 80, 90
+    );
+
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d1));
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d2));
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d3));
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d4));
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d5));
+    if (isptrlist) {
+        inserted = cxListInsertUniqueArray(list, d6ptr, 6);
+    } else {
+        inserted = cxListInsertUniqueArray(list, d6a, 6);
+    }
+    CX_TEST_ASSERT(inserted == 6);
+    if (isptrlist) {
+        inserted = cxListInsertUniqueArray(list, d7ptr, 6);
+    } else {
+        inserted = cxListInsertUniqueArray(list, d7a, 6);
+    }
+    CX_TEST_ASSERT(inserted == 6);
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d8));
+    CX_TEST_ASSERT(0 == cxListInsertUnique(list, &d9));
+    if (isptrlist) {
+        inserted = cxListInsertUniqueArray(list, d10ptr, 3);
+    } else {
+        inserted = cxListInsertUniqueArray(list, d10a, 3);
+    }
+    CX_TEST_ASSERT(inserted == 3);
+    CX_TEST_ASSERT(cxListSize(list) == 19);
+    for (size_t i = 0; i < 19; i++) {
         CX_TEST_ASSERT(*(int *) cxListAt(list, i) == expected[i]);
     }
 })
@@ -2173,6 +2423,7 @@
     cx_test_register(suite, test_array_copy_unsupported_width);
     cx_test_register(suite, test_array_reserve);
     cx_test_register(suite, test_array_insert_sorted);
+    cx_test_register(suite, test_array_insert_unique);
     cx_test_register(suite, test_array_binary_search);
 
     cx_test_register(suite, test_list_arl_create);
@@ -2192,6 +2443,8 @@
     cx_test_register(suite, test_list_parl_insert_array);
     cx_test_register(suite, test_list_arl_insert_sorted);
     cx_test_register(suite, test_list_parl_insert_sorted);
+    cx_test_register(suite, test_list_arl_insert_unique);
+    cx_test_register(suite, test_list_parl_insert_unique);
     cx_test_register(suite, test_list_arl_remove);
     cx_test_register(suite, test_list_parl_remove);
     cx_test_register(suite, test_list_arl_remove_and_get);
@@ -2247,6 +2500,8 @@
     cx_test_register(suite, test_list_parlm_insert_array);
     cx_test_register(suite, test_list_arlm_insert_sorted);
     cx_test_register(suite, test_list_parlm_insert_sorted);
+    cx_test_register(suite, test_list_arlm_insert_unique);
+    cx_test_register(suite, test_list_parlm_insert_unique);
     cx_test_register(suite, test_list_arlm_swap);
     cx_test_register(suite, test_list_parlm_swap);
     cx_test_register(suite, test_list_arlm_sort);
@@ -2272,6 +2527,7 @@
     cx_test_register(suite, test_linked_list_insert);
     cx_test_register(suite, test_linked_list_insert_chain);
     cx_test_register(suite, test_linked_list_insert_sorted);
+    cx_test_register(suite, test_linked_list_insert_unique);
     cx_test_register(suite, test_linked_list_first);
     cx_test_register(suite, test_linked_list_last);
     cx_test_register(suite, test_linked_list_prev);
@@ -2299,6 +2555,8 @@
     cx_test_register(suite, test_list_pll_insert_array);
     cx_test_register(suite, test_list_ll_insert_sorted);
     cx_test_register(suite, test_list_pll_insert_sorted);
+    cx_test_register(suite, test_list_ll_insert_unique);
+    cx_test_register(suite, test_list_pll_insert_unique);
     cx_test_register(suite, test_list_ll_remove);
     cx_test_register(suite, test_list_pll_remove);
     cx_test_register(suite, test_list_ll_remove_and_get);
@@ -2353,6 +2611,8 @@
     cx_test_register(suite, test_list_pllm_insert_array);
     cx_test_register(suite, test_list_llm_insert_sorted);
     cx_test_register(suite, test_list_pllm_insert_sorted);
+    cx_test_register(suite, test_list_llm_insert_unique);
+    cx_test_register(suite, test_list_pllm_insert_unique);
     cx_test_register(suite, test_list_llm_swap);
     cx_test_register(suite, test_list_pllm_swap);
     cx_test_register(suite, test_list_llm_sort);
@@ -2379,6 +2639,8 @@
     cx_test_register(suite, test_list_pkvl_insert_array);
     cx_test_register(suite, test_list_kvl_insert_sorted);
     cx_test_register(suite, test_list_pkvl_insert_sorted);
+    cx_test_register(suite, test_list_kvl_insert_unique);
+    cx_test_register(suite, test_list_pkvl_insert_unique);
     cx_test_register(suite, test_list_kvl_remove);
     cx_test_register(suite, test_list_pkvl_remove);
     cx_test_register(suite, test_list_kvl_remove_and_get);

mercurial