add tests for cxListDifference() - resolves #751

Thu, 30 Oct 2025 19:26:47 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 30 Oct 2025 19:26:47 +0100
changeset 1462
9263d3f15379
parent 1461
dfd79d615049
child 1463
e228b5bde7f6

add tests for cxListDifference() - resolves #751

tests/test_list.c file | annotate | diff | comparison | revisions
tests/ucxtest.c file | annotate | diff | comparison | revisions
--- a/tests/test_list.c	Tue Oct 28 22:09:55 2025 +0100
+++ b/tests/test_list.c	Thu Oct 30 19:26:47 2025 +0100
@@ -2526,15 +2526,23 @@
     free(testdata);
 })
 
+static bool test_clone_func_max_enabled = false;
 static unsigned test_clone_func_max_clones;
 static void *test_clone_func(void *dest, const void *src, const CxAllocator *al, void *data) {
-    if (test_clone_func_max_clones == 0) return NULL;
-    test_clone_func_max_clones--;
+    if (test_clone_func_max_enabled) {
+        if (test_clone_func_max_clones == 0) return NULL;
+        test_clone_func_max_clones--;
+    }
 
     if (dest == NULL) {
         dest = cxMalloc(al, sizeof(int));
     }
 
+    int z = 0;
+    if (data == NULL) {
+        data = &z;
+    }
+
     *((int*) dest) = *(int*) src + *(int*) data;
     (*(int*) data)++;
 
@@ -2573,7 +2581,6 @@
     // perform the test
     int expected_data[12] = array_init(1, 2, 3, 4, 1, 3, 5, 7, 9, 11, 13, 15);
     int c = 0;
-    test_clone_func_max_clones = 100; // no limit
     CX_TEST_ASSERT(0 == cxListClone(target, source, test_clone_func, testing_alloc, &c));
     CX_TEST_ASSERT(c == 8);
     CX_TEST_ASSERT(cxListSize(target) == 12);
@@ -2621,8 +2628,10 @@
     // perform the test
     int expected_data[9] = array_init(1, 2, 3, 4, 1, 3, 5, 7, 9);
     int c = 0;
+    test_clone_func_max_enabled = true;
     test_clone_func_max_clones = 5;
     CX_TEST_ASSERT(0 != cxListClone(target, source, test_clone_func, testing_alloc, &c));
+    test_clone_func_max_enabled = false;
     CX_TEST_ASSERT(c == 5);
     CX_TEST_ASSERT(cxListSize(target) == 9);
     CX_TEST_ASSERT(cxListSize(source) == 8);
@@ -2677,6 +2686,107 @@
     CX_TEST_CALL_SUBROUTINE(verify_clone_alloc_fail, target, list, true);
 })
 
+static CX_TEST_SUBROUTINE(verify_difference, bool sorted, bool alloc_fail) {
+    CxTestingAllocator talloc;
+    cx_testing_allocator_init(&talloc);
+
+    CxList *dst = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS);
+    cxDefineAdvancedDestructor(dst, cxFree, &talloc);
+    CxList *minuend = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int));
+    CxList *subtrahend = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int));
+
+    int dst_data[] = {
+        47, 178, 176, 83, 109, 149, 192, 38, 101, 116, 121, 73, 94, 197, 91, 79, 158, 86, 190, 138, 100, 39, 30, 144,
+        35, 182, 155, 84, 139, 186, 67, 123, 62, 37, 3, 64, 172, 56, 160, 1, 156, 132, 131, 49, 10, 126, 171, 145, 77,
+        107
+    };
+    int minuend_data[] = {
+        153, 106, 171, 130, 74, 173, 150, 94, 27, 92, 70, 175, 200, 20, 29, 161, 88, 116, 71, 53, 199, 124, 32, 9, 76,
+        151, 33, 51, 37, 65, 176, 49, 12, 162, 28, 85, 4, 177, 198, 54, 109, 188, 44, 77, 194, 63, 41, 129, 97, 83
+    };
+    int subtrahend_data[] = {
+        75, 137, 176, 111, 85, 27, 197, 141, 46, 103, 69, 146, 49, 79, 63, 130, 154, 45, 38, 139, 193, 90, 64, 142, 115,
+        120, 78, 100, 101, 42, 21, 1, 161, 10, 114, 198, 181, 178, 136, 188, 59, 41, 73, 99, 151, 144, 118, 53, 199, 71
+    };
+
+    {
+        CxList *tmp = cxArrayListCreateSimple(sizeof(int), 50);
+        cxListAddArray(tmp, dst_data, 50);
+        cxListClone(dst, tmp, test_clone_func, &talloc.base, NULL);
+        cxListFree(tmp);
+    }
+    cxListAddArray(minuend, minuend_data, 50);
+    cxListAddArray(subtrahend, subtrahend_data, 50);
+    if (sorted) {
+        cxListSort(dst);
+        cxListSort(minuend);
+        cxListSort(subtrahend);
+    }
+
+    // expected 36 elements stay in dst, and 36 will be added from the difference
+    size_t expected_len = 72;
+    int expected_unsorted[] = {
+        47, 83, 109, 149, 192, 116, 121, 94, 91, 158, 86, 190, 138, 39, 30, 35, 182, 155, 84, 186, 67, 123, 62, 37,
+        3, 172, 56, 160, 156, 132, 131, 126, 171, 145, 77, 107,
+        153, 106, 171, 74, 173, 150, 94, 92, 70, 175, 200, 20, 29, 88, 116, 124, 32, 9, 76, 33, 51, 37, 65, 12, 162,
+        28, 4, 177, 54, 109, 44, 77, 194, 129, 97, 83
+    };
+    int expected_sorted[] = {
+        3, 30, 35, 37, 39, 47, 56, 62, 67, 77, 83, 84, 86, 91, 94, 107, 109, 116, 121, 123, 126, 131, 132, 138, 145,
+        149, 155, 156, 158, 160, 171, 172, 182, 186, 190, 192,
+        4, 9, 12, 20, 28, 29, 32, 33, 37, 44, 51, 54, 65, 70, 74, 76, 77, 83, 88, 92, 94, 97, 106, 109, 116, 124, 129,
+        150, 153, 162, 171, 173, 175, 177, 194, 200
+    };
+
+    if (alloc_fail) {
+        test_clone_func_max_enabled = true;
+        test_clone_func_max_clones = 30;
+        expected_len = 66;
+    }
+    CxList *expected = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int), expected_len);
+    cxListAddArray(expected, sorted ? expected_sorted : expected_unsorted, expected_len);
+
+    int result = cxListDifference(dst, minuend, subtrahend, test_clone_func, &talloc.base, NULL);
+    if (alloc_fail) {
+        CX_TEST_ASSERT(result != 0);
+    } else {
+        CX_TEST_ASSERT(result == 0);
+    }
+    test_clone_func_max_enabled = false;
+    CX_TEST_ASSERT(expected_len == cxListSize(dst));
+    CX_TEST_ASSERT(0 == cxListCompare(dst, expected));
+
+    cxListFree(dst);
+    cxListFree(minuend);
+    cxListFree(subtrahend);
+    cxListFree(expected);
+    CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
+}
+
+CX_TEST(test_list_difference_unsorted) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(verify_difference, false, false);
+    }
+}
+
+CX_TEST(test_list_difference_sorted) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(verify_difference, true, false);
+    }
+}
+
+CX_TEST(test_list_difference_unsorted_alloc_fail) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(verify_difference, false, true);
+    }
+}
+
+CX_TEST(test_list_difference_sorted_alloc_fail) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(verify_difference, true, true);
+    }
+}
+
 CX_TEST(test_list_pointer_list_supports_null) {
     CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS);
     int x = 47;
@@ -3128,6 +3238,18 @@
     return suite;
 }
 
+CxTestSuite *cx_test_suite_list_set_ops(void) {
+    CxTestSuite *suite = cx_test_suite_new("list collection operations");
+
+    // we do not perform the following tests with every combination of list types
+    cx_test_register(suite, test_list_difference_unsorted);
+    cx_test_register(suite, test_list_difference_sorted);
+    cx_test_register(suite, test_list_difference_unsorted_alloc_fail);
+    cx_test_register(suite, test_list_difference_sorted_alloc_fail);
+
+    return suite;
+}
+
 CxTestSuite *cx_test_suite_list_corner_cases(void) {
     CxTestSuite *suite = cx_test_suite_new("list corner cases");
 
--- a/tests/ucxtest.c	Tue Oct 28 22:09:55 2025 +0100
+++ b/tests/ucxtest.c	Thu Oct 30 19:26:47 2025 +0100
@@ -48,6 +48,7 @@
 CxTestSuite *cx_test_suite_linked_list_defaulted_funcs(void);
 CxTestSuite *cx_test_suite_kv_list(void);
 CxTestSuite *cx_test_suite_kv_list_specifics(void);
+CxTestSuite *cx_test_suite_list_set_ops(void);
 CxTestSuite *cx_test_suite_list_corner_cases(void);
 CxTestSuite *cx_test_suite_tree_low_level(void);
 CxTestSuite *cx_test_suite_tree_high_level(void);
@@ -102,6 +103,7 @@
             cx_test_suite_linked_list_defaulted_funcs(),
             cx_test_suite_kv_list(),
             cx_test_suite_kv_list_specifics(),
+            cx_test_suite_list_set_ops(),
             cx_test_suite_list_corner_cases(),
             cx_test_suite_tree_low_level(),
             cx_test_suite_tree_high_level(),

mercurial