#include "cx/test.h"
#include "util_allocator.h"
#include "cx/compare.h"
#include "cx/array_list.h"
#include "cx/linked_list.h"
#include "cx/kv_list.h"
#include <stdarg.h>
#include <errno.h>
CX_TEST(test_array_add) {
CX_ARRAY_DECLARE(
int, arr);
arr = cxCallocDefault(
5,
sizeof(
int));
arr[
0] =
2;
arr[
1] =
3;
arr[
2] =
5;
arr[
3] =
7;
arr[
4] =
11;
arr_size =
3;
arr_capacity =
5;
int elem =
8, elem2 =
47;
int result;
CX_TEST_DO {
result = cx_array_simple_add(arr, elem);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr[
0] ==
2);
CX_TEST_ASSERT(arr[
1] ==
3);
CX_TEST_ASSERT(arr[
2] ==
5);
CX_TEST_ASSERT(arr[
3] ==
8);
CX_TEST_ASSERT(arr[
4] ==
11);
CX_TEST_ASSERT(arr_size ==
4);
CX_TEST_ASSERT(arr_capacity ==
5);
arr_size =
5;
result = cx_array_simple_add(arr, elem2);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr[
0] ==
2);
CX_TEST_ASSERT(arr[
1] ==
3);
CX_TEST_ASSERT(arr[
2] ==
5);
CX_TEST_ASSERT(arr[
3] ==
8);
CX_TEST_ASSERT(arr[
4] ==
11);
CX_TEST_ASSERT(arr[
5] ==
47);
CX_TEST_ASSERT(arr_size ==
6);
CX_TEST_ASSERT(arr_capacity >=
6);
}
cxFreeDefault(arr);
}
CX_TEST(test_array_add8) {
CX_ARRAY_DECLARE_SIZED(
int, arr,
uint8_t);
arr = cxCallocDefault(
5,
sizeof(
int));
arr[
0] =
2;
arr[
1] =
3;
arr[
2] =
5;
arr[
3] =
7;
arr[
4] =
11;
arr_size =
3;
arr_capacity =
5;
int elem =
8, elem2 =
47;
int result;
CX_TEST_DO {
result = cx_array_simple_add(arr, elem);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr[
0] ==
2);
CX_TEST_ASSERT(arr[
1] ==
3);
CX_TEST_ASSERT(arr[
2] ==
5);
CX_TEST_ASSERT(arr[
3] ==
8);
CX_TEST_ASSERT(arr[
4] ==
11);
CX_TEST_ASSERT(arr_size ==
4);
CX_TEST_ASSERT(arr_capacity ==
5);
arr_size =
5;
result = cx_array_simple_add(arr, elem2);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr[
0] ==
2);
CX_TEST_ASSERT(arr[
1] ==
3);
CX_TEST_ASSERT(arr[
2] ==
5);
CX_TEST_ASSERT(arr[
3] ==
8);
CX_TEST_ASSERT(arr[
4] ==
11);
CX_TEST_ASSERT(arr[
5] ==
47);
CX_TEST_ASSERT(arr_size ==
6);
CX_TEST_ASSERT(arr_capacity >=
6);
result = cx_array_simple_copy(arr,
260, &elem,
1);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(errno ==
EOVERFLOW);
CX_TEST_ASSERT(arr_size ==
6);
CX_TEST_ASSERT(arr_capacity <
128);
}
cxFreeDefault(arr);
}
CX_TEST(test_array_add16) {
CX_ARRAY_DECLARE_SIZED(
char, arr,
uint16_t);
cx_array_initialize(arr,
300);
arr_size =
270;
int result;
CX_TEST_DO {
char elem =
'A';
result = cx_array_simple_add(arr, elem);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr[
270] ==
'A');
CX_TEST_ASSERT(arr_size ==
271);
CX_TEST_ASSERT(arr_capacity ==
300);
char *hello =
"Hello";
result = cx_array_simple_copy(arr,
9000, hello,
5);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr[
9000] ==
'H');
CX_TEST_ASSERT(arr[
9001] ==
'e');
CX_TEST_ASSERT(arr[
9002] ==
'l');
CX_TEST_ASSERT(arr[
9003] ==
'l');
CX_TEST_ASSERT(arr[
9004] ==
'o');
CX_TEST_ASSERT(arr_size ==
9005);
CX_TEST_ASSERT(arr_capacity ==
9*
1024);
result = cx_array_simple_copy(arr,
65532, hello,
5);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(errno ==
EOVERFLOW);
CX_TEST_ASSERT(arr_size ==
9005);
CX_TEST_ASSERT(arr_capacity ==
9*
1024);
}
cxFreeDefault(arr);
}
CX_TEST(test_array_copy_unsupported_width) {
CX_ARRAY_DECLARE_SIZED(
int, arr,
uint16_t);
cx_array_initialize(arr,
16);
int result;
CX_TEST_DO {
int elem =
5;
result = cx_array_copy(
(
void **) &(arr),
&(arr_size),
&(arr_capacity),
12,
5,
&elem,
sizeof(
int),
1,
cx_array_default_reallocator
);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(errno ==
EINVAL);
CX_TEST_ASSERT(arr_size ==
0);
CX_TEST_ASSERT(arr_capacity ==
16);
}
cxFreeDefault(arr);
}
CX_TEST(test_array_copy_overlap) {
CX_ARRAY_DECLARE_SIZED(
char, arr,
uint8_t);
cx_array_initialize(arr,
16);
strcpy(arr,
"Hello, World!");
CX_TEST_DO {
errno =
0;
int result = cx_array_simple_copy(arr,
7, arr,
14);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(errno ==
0);
CX_TEST_ASSERT(arr_size ==
21);
CX_TEST_ASSERT(arr_capacity ==
32);
CX_TEST_ASSERT(
0 == memcmp(arr,
"Hello, Hello, World!\0",
21));
}
cxFreeDefault(arr);
}
CX_TEST(test_array_reserve) {
{
CX_ARRAY_DECLARE(
int, arr);
cx_array_initialize(arr,
16);
int result;
CX_TEST_DO {
result = cx_array_reserve(
(
void **) &(arr),
&(arr_size),
&(arr_capacity),
0,
sizeof(
int),
30,
cx_array_default_reallocator
);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(arr_size ==
0);
CX_TEST_ASSERT(arr_capacity ==
30);
}
cxFreeDefault(arr);
}
{
CX_ARRAY_DECLARE_SIZED(
char, arr,
uint16_t);
cx_array_initialize(arr,
16);
arr_size =
5;
int result;
CX_TEST_DO {
errno =
0;
result = cx_array_simple_reserve(arr,
3);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(errno ==
0);
CX_TEST_ASSERT(arr_size ==
5);
CX_TEST_ASSERT(arr_capacity ==
16);
result = cx_array_simple_reserve(arr,
20);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(errno ==
0);
CX_TEST_ASSERT(arr_size ==
5);
CX_TEST_ASSERT(arr_capacity ==
25);
result = cx_array_simple_reserve(arr,
2000);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(errno ==
0);
CX_TEST_ASSERT(arr_size ==
5);
CX_TEST_ASSERT(arr_capacity ==
2005);
result = cx_array_simple_reserve(arr,
70000);
CX_TEST_ASSERT(result ==
1);
CX_TEST_ASSERT(errno ==
EOVERFLOW);
CX_TEST_ASSERT(arr_size ==
5);
CX_TEST_ASSERT(arr_capacity ==
2005);
}
cxFreeDefault(arr);
}
{
CX_ARRAY_DECLARE_SIZED(
char, arr,
uint8_t);
cx_array_initialize(arr,
16);
arr_size =
5;
int result;
CX_TEST_DO {
errno =
0;
result = cx_array_simple_reserve(arr,
3);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(errno ==
0);
CX_TEST_ASSERT(arr_size ==
5);
CX_TEST_ASSERT(arr_capacity ==
16);
result = cx_array_simple_reserve(arr,
20);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(errno ==
0);
CX_TEST_ASSERT(arr_size ==
5);
CX_TEST_ASSERT(arr_capacity ==
25);
arr_size =
10;
result = cx_array_simple_reserve(arr,
250);
CX_TEST_ASSERT(result ==
1);
CX_TEST_ASSERT(errno ==
EOVERFLOW);
CX_TEST_ASSERT(arr_size ==
10);
CX_TEST_ASSERT(arr_capacity ==
25);
}
cxFreeDefault(arr);
}
}
CX_TEST(test_array_reserve_unsupported_width) {
CX_ARRAY_DECLARE_SIZED(
int, arr,
uint16_t);
cx_array_initialize(arr,
16);
int result;
CX_TEST_DO {
result = cx_array_reserve(
(
void **) &(arr),
&(arr_size),
&(arr_capacity),
12,
sizeof(
int),
30,
cx_array_default_reallocator
);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(errno ==
EINVAL);
CX_TEST_ASSERT(arr_size ==
0);
CX_TEST_ASSERT(arr_capacity ==
16);
}
cxFreeDefault(arr);
}
CX_TEST(test_array_insert_sorted) {
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 d11a[
6] = {
58,
59,
71,
71,
72,
75};
int d12a[
3] = {
10,
120,
130};
int expected[
31] = {
10,
40,
50,
51,
52,
54,
56,
56,
57,
58,
58,
59,
60,
62,
64,
65,
67,
70,
71,
71,
72,
75,
75,
75,
77,
78,
80,
90,
90,
120,
130
};
CX_ARRAY_DECLARE(
int, array);
cx_array_initialize(array,
4);
CX_TEST_DO {
CX_TEST_ASSERT(
0 == cx_array_simple_add_sorted(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_sorted(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_sorted(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_sorted(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_sorted(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_sorted(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_sorted(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_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 == cx_array_simple_insert_sorted(array, d11a,
6, cx_cmp_int));
CX_TEST_ASSERT(array_size ==
28);
CX_TEST_ASSERT(array_capacity >=
28);
CX_TEST_ASSERT(
0 == cx_array_simple_insert_sorted(array, d12a,
3, cx_cmp_int));
CX_TEST_ASSERT(array_size ==
31);
CX_TEST_ASSERT(array_capacity >=
31);
CX_TEST_ASSERT(
0 == memcmp(array, expected,
31 *
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 d11a[
8] = {
90,
90,
90,
95,
95,
100,
110,
110};
int expected[
22] = {
40,
50,
51,
52,
54,
56,
57,
58,
60,
62,
64,
65,
67,
70,
75,
77,
78,
80,
90,
95,
100,
110
};
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 == cx_array_simple_insert_unique(array, d11a,
8, cx_cmp_int));
CX_TEST_ASSERT(array_size ==
22);
CX_TEST_ASSERT(array_capacity >=
22);
CX_TEST_ASSERT(
0 == memcmp(array, expected,
22 *
sizeof(
int)));
}
cxFreeDefault(array);
}
CX_TEST(test_array_binary_search) {
int array[
18] = {
40,
50,
51,
52,
54,
56,
57,
58,
60,
62,
64,
65,
70,
75,
77,
78,
80,
90
};
CX_TEST_DO {
for (
size_t i =
0; i <
18; i++) {
CX_TEST_ASSERT(i == cx_array_binary_search(array,
18,
sizeof(
int), &array[i], cx_cmp_int));
}
int s =
58;
CX_TEST_ASSERT(
7 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
7 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
60;
CX_TEST_ASSERT(
8 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
8 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
59;
CX_TEST_ASSERT(
7 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
8 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
79;
CX_TEST_ASSERT(
15 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
16 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
66;
CX_TEST_ASSERT(
11 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
12 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
69;
CX_TEST_ASSERT(
11 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
12 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
95;
CX_TEST_ASSERT(
17 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
30;
CX_TEST_ASSERT(
18 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
0 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
40;
CX_TEST_ASSERT(
0 == cx_array_binary_search_inf(array,
0,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
0 == cx_array_binary_search_sup(array,
0,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
0 == cx_array_binary_search(array,
0,
sizeof(
int), &s, cx_cmp_int));
s =
30;
CX_TEST_ASSERT(
1 == cx_array_binary_search_inf(array,
1,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
0 == cx_array_binary_search_sup(array,
1,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
1 == cx_array_binary_search(array,
1,
sizeof(
int), &s, cx_cmp_int));
s =
50;
CX_TEST_ASSERT(
0 == cx_array_binary_search_inf(array,
1,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
1 == cx_array_binary_search_sup(array,
1,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
1 == cx_array_binary_search(array,
1,
sizeof(
int), &s, cx_cmp_int));
s =
40;
CX_TEST_ASSERT(
0 == cx_array_binary_search_inf(array,
1,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
0 == cx_array_binary_search_sup(array,
1,
sizeof(
int), &s, cx_cmp_int));
CX_TEST_ASSERT(
0 == cx_array_binary_search(array,
1,
sizeof(
int), &s, cx_cmp_int));
}
}
CX_TEST(test_array_binary_search_with_duplicates) {
int array[
18] = {
40,
50,
55,
55,
55,
57,
57,
58,
60,
62,
64,
65,
70,
70,
70,
78,
80,
90
};
int s;
CX_TEST_DO {
s =
40;
CX_TEST_ASSERT(
0 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
50;
CX_TEST_ASSERT(
1 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
55;
CX_TEST_ASSERT(
4 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
57;
CX_TEST_ASSERT(
6 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
58;
CX_TEST_ASSERT(
7 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
65;
CX_TEST_ASSERT(
11 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
70;
CX_TEST_ASSERT(
14 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
78;
CX_TEST_ASSERT(
15 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
30;
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
75;
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
52;
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
100;
CX_TEST_ASSERT(
18 == cx_array_binary_search(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
55;
CX_TEST_ASSERT(
4 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
56;
CX_TEST_ASSERT(
4 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
75;
CX_TEST_ASSERT(
14 == cx_array_binary_search_inf(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
52;
CX_TEST_ASSERT(
2 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
66;
CX_TEST_ASSERT(
12 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
75;
CX_TEST_ASSERT(
15 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
s =
70;
CX_TEST_ASSERT(
12 == cx_array_binary_search_sup(array,
18,
sizeof(
int), &s, cx_cmp_int));
}
}
typedef struct node {
struct node *next;
struct node *prev;
int data;
} node;
static int test_cmp_node(
const void *l,
const void *r) {
const node *left = l;
const node *right = r;
return left->data - right->data;
}
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 node *create_nodes_test_data(
size_t len) {
node *begin = calloc(
1,
sizeof(node));
void *prev = begin;
for (
size_t i =
1; i < len; i++) {
node *n = calloc(
1,
sizeof(node));
cx_linked_list_link(prev, n, loc_prev, loc_next);
prev = n;
}
return begin;
}
void assign_nodes_test_data(node *n, ...) {
va_list ap;
va_start(ap, n);
while (n !=
NULL) {
n->data = va_arg(ap,
int);
n = n->next;
}
va_end(ap);
}
static void destroy_nodes_test_data(node *n) {
while (n !=
NULL) {
void *next = n->next;
free(n);
n = next;
}
}
static int *int_test_data(
size_t len) {
int *data = malloc(len*
sizeof(
int));
for (
size_t i =
0 ; i < len ; i++) {
data[i] = rand();
}
return data;
}
CX_TEST(test_linked_list_link_unlink) {
node a = {
0}, b = {
0}, c = {
0};
CX_TEST_DO {
cx_linked_list_link(&a, &b, loc_prev, loc_next);
CX_TEST_ASSERT(a.prev ==
NULL);
CX_TEST_ASSERT(a.next == &b);
CX_TEST_ASSERT(b.prev == &a);
CX_TEST_ASSERT(b.next ==
NULL);
cx_linked_list_unlink(&a, &b, loc_prev, loc_next);
CX_TEST_ASSERT(a.prev ==
NULL);
CX_TEST_ASSERT(a.next ==
NULL);
CX_TEST_ASSERT(b.prev ==
NULL);
CX_TEST_ASSERT(b.next ==
NULL);
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);
CX_TEST_ASSERT(a.prev ==
NULL);
CX_TEST_ASSERT(a.next == &b);
CX_TEST_ASSERT(b.prev == &a);
CX_TEST_ASSERT(b.next ==
NULL);
CX_TEST_ASSERT(c.prev ==
NULL);
CX_TEST_ASSERT(c.next ==
NULL);
}
}
CX_TEST(test_linked_list_at) {
node a = {
0}, b = {
0}, c = {
0}, d = {
0};
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);
CX_TEST_DO {
CX_TEST_ASSERT(cx_linked_list_at(&a,
0, loc_next,
0) == &a);
CX_TEST_ASSERT(cx_linked_list_at(&a,
0, loc_next,
1) == &b);
CX_TEST_ASSERT(cx_linked_list_at(&a,
0, loc_next,
2) == &c);
CX_TEST_ASSERT(cx_linked_list_at(&a,
0, loc_next,
3) == &d);
CX_TEST_ASSERT(cx_linked_list_at(&a,
0, loc_next,
4) ==
NULL);
CX_TEST_ASSERT(cx_linked_list_at(&b,
1, loc_prev,
0) == &a);
CX_TEST_ASSERT(cx_linked_list_at(&b,
1, loc_next,
1) == &b);
CX_TEST_ASSERT(cx_linked_list_at(&b,
1, loc_next,
2) == &c);
CX_TEST_ASSERT(cx_linked_list_at(&b,
1, loc_next,
3) == &d);
CX_TEST_ASSERT(cx_linked_list_at(&b,
1, loc_next,
4) ==
NULL);
CX_TEST_ASSERT(cx_linked_list_at(&d,
3, loc_prev,
0) == &a);
CX_TEST_ASSERT(cx_linked_list_at(&d,
3, loc_prev,
1) == &b);
}
}
CX_TEST(test_linked_list_find) {
node *list = create_nodes_test_data(
4);
assign_nodes_test_data(list,
2,
4,
6,
8);
CX_TEST_DO {
size_t i =
10;
int s;
s =
2;
node *n = list;
CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s, &i) == n);
CX_TEST_ASSERT(i ==
0);
n = n->next;
s =
4;
CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s, &i) == n);
CX_TEST_ASSERT(i ==
1);
n = n->next;
s =
6;
CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s, &i) == n);
CX_TEST_ASSERT(i ==
2);
n = n->next;
s =
8;
CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s, &i) == n);
CX_TEST_ASSERT(i ==
3);
s =
10;
CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s, &i) ==
NULL);
s =
-2;
CX_TEST_ASSERT(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s, &i) ==
NULL);
}
destroy_nodes_test_data(list);
}
CX_TEST(test_linked_list_compare) {
void *la = create_nodes_test_data(
4);
void *lb = create_nodes_test_data(
3);
void *lc = create_nodes_test_data(
4);
assign_nodes_test_data(la,
2,
4,
6,
8);
assign_nodes_test_data(lb,
2,
4,
6);
assign_nodes_test_data(lc,
2,
4,
6,
9);
CX_TEST_DO {
CX_TEST_ASSERT(cx_linked_list_compare(la, lb, loc_next, loc_data, cx_cmp_int) >
0);
CX_TEST_ASSERT(cx_linked_list_compare(lb, la, loc_next, loc_data, cx_cmp_int) <
0);
CX_TEST_ASSERT(cx_linked_list_compare(lc, la, loc_next, loc_data, cx_cmp_int) >
0);
CX_TEST_ASSERT(cx_linked_list_compare(la, lc, loc_next, loc_data, cx_cmp_int) <
0);
CX_TEST_ASSERT(cx_linked_list_compare(la, la, loc_next, loc_data, cx_cmp_int) ==
0);
}
destroy_nodes_test_data(la);
destroy_nodes_test_data(lb);
destroy_nodes_test_data(lc);
}
CX_TEST(test_linked_list_add) {
node nodes[
4];
void *begin, *end;
CX_TEST_DO {
memset(nodes,
0,
sizeof(node)*
4);
end = begin =
NULL;
cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[
0]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].prev ==
NULL);
CX_TEST_ASSERT(nodes[
0].next ==
NULL);
cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[
1]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
1]);
CX_TEST_ASSERT(nodes[
0].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev == &nodes[
0]);
memset(nodes,
0,
sizeof(node)*
4);
end = begin =
NULL;
cx_linked_list_add(&begin,
NULL, loc_prev, loc_next, &nodes[
0]);
CX_TEST_ASSERT(begin == &nodes[
0]);
cx_linked_list_add(&begin,
NULL, loc_prev, loc_next, &nodes[
1]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev == &nodes[
0]);
cx_linked_list_add(&begin,
NULL, loc_prev, loc_next, &nodes[
2]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
2]);
CX_TEST_ASSERT(nodes[
2].prev == &nodes[
1]);
memset(nodes,
0,
sizeof(node)*
4);
end = begin =
NULL;
cx_linked_list_add(
NULL, &end, loc_prev, loc_next, &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
0]);
cx_linked_list_add(
NULL, &end, loc_prev, loc_next, &nodes[
1]);
CX_TEST_ASSERT(end == &nodes[
1]);
CX_TEST_ASSERT(nodes[
0].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev == &nodes[
0]);
cx_linked_list_add(
NULL, &end, loc_prev, loc_next, &nodes[
2]);
CX_TEST_ASSERT(end == &nodes[
2]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
2]);
CX_TEST_ASSERT(nodes[
2].prev == &nodes[
1]);
memset(nodes,
0,
sizeof(node)*
4);
end = begin =
NULL;
cx_linked_list_add(&begin, &end,
-1, loc_next, &nodes[
0]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
0]);
cx_linked_list_add(&begin, &end,
-1, loc_next, &nodes[
1]);
CX_TEST_ASSERT(end == &nodes[
1]);
CX_TEST_ASSERT(nodes[
0].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev ==
NULL);
}
}
CX_TEST(test_linked_list_prepend) {
node nodes[
4];
void *begin, *end;
CX_TEST_DO {
memset(nodes,
0,
sizeof(node) *
4);
end = begin =
NULL;
cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[
0]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].prev ==
NULL);
CX_TEST_ASSERT(nodes[
0].next ==
NULL);
cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[
1]);
CX_TEST_ASSERT(begin == &nodes[
1]);
CX_TEST_ASSERT(end == &nodes[
0]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].prev == &nodes[
1]);
memset(nodes,
0,
sizeof(node) *
4);
end = begin =
NULL;
cx_linked_list_prepend(&begin,
NULL, loc_prev, loc_next, &nodes[
0]);
CX_TEST_ASSERT(begin == &nodes[
0]);
cx_linked_list_prepend(&begin,
NULL, loc_prev, loc_next, &nodes[
1]);
CX_TEST_ASSERT(begin == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].prev == &nodes[
1]);
cx_linked_list_prepend(&begin,
NULL, loc_prev, loc_next, &nodes[
2]);
CX_TEST_ASSERT(begin == &nodes[
2]);
CX_TEST_ASSERT(nodes[
2].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev == &nodes[
2]);
memset(nodes,
0,
sizeof(node) *
4);
end = begin =
NULL;
cx_linked_list_prepend(
NULL, &end, loc_prev, loc_next, &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
0]);
cx_linked_list_prepend(
NULL, &end, loc_prev, loc_next, &nodes[
1]);
CX_TEST_ASSERT(end == &nodes[
0]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].prev == &nodes[
1]);
cx_linked_list_prepend(
NULL, &end, loc_prev, loc_next, &nodes[
2]);
CX_TEST_ASSERT(end == &nodes[
0]);
CX_TEST_ASSERT(nodes[
2].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev == &nodes[
2]);
memset(nodes,
0,
sizeof(node) *
4);
end = begin =
NULL;
cx_linked_list_prepend(&begin, &end,
-1, loc_next, &nodes[
0]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(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]);
CX_TEST_ASSERT(begin == &nodes[
2]);
CX_TEST_ASSERT(end == &nodes[
0]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
0]);
CX_TEST_ASSERT(nodes[
2].next == &nodes[
1]);
CX_TEST_ASSERT(nodes[
1].prev ==
NULL);
CX_TEST_ASSERT(nodes[
0].prev ==
NULL);
}
}
CX_TEST(test_linked_list_insert) {
node nodes[
4];
void *begin, *end;
CX_TEST_DO {
memset(nodes,
0,
sizeof(node) *
4);
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]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
2]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
3]);
CX_TEST_ASSERT(nodes[
2].prev == &nodes[
3]);
CX_TEST_ASSERT(nodes[
3].prev == &nodes[
1]);
CX_TEST_ASSERT(nodes[
3].next == &nodes[
2]);
memset(nodes,
0,
sizeof(node) *
4);
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]);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
3]);
CX_TEST_ASSERT(nodes[
2].next == &nodes[
3]);
CX_TEST_ASSERT(nodes[
3].prev == &nodes[
2]);
CX_TEST_ASSERT(nodes[
3].next ==
NULL);
memset(nodes,
0,
sizeof(node) *
4);
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]);
CX_TEST_ASSERT(begin == &nodes[
3]);
CX_TEST_ASSERT(end == &nodes[
2]);
CX_TEST_ASSERT(nodes[
0].prev == &nodes[
3]);
CX_TEST_ASSERT(nodes[
3].prev ==
NULL);
CX_TEST_ASSERT(nodes[
3].next == &nodes[
0]);
}
}
CX_TEST(test_linked_list_insert_chain) {
node nodes[
5];
void *begin, *end;
CX_TEST_DO {
memset(nodes,
0,
sizeof(node) *
5);
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);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
2]);
CX_TEST_ASSERT(nodes[
1].next == &nodes[
3]);
CX_TEST_ASSERT(nodes[
2].prev == &nodes[
4]);
CX_TEST_ASSERT(nodes[
3].prev == &nodes[
1]);
CX_TEST_ASSERT(nodes[
4].next == &nodes[
2]);
memset(nodes,
0,
sizeof(node) *
5);
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);
CX_TEST_ASSERT(begin == &nodes[
0]);
CX_TEST_ASSERT(end == &nodes[
4]);
CX_TEST_ASSERT(nodes[
2].next == &nodes[
3]);
CX_TEST_ASSERT(nodes[
3].prev == &nodes[
2]);
CX_TEST_ASSERT(nodes[
4].next ==
NULL);
memset(nodes,
0,
sizeof(node) *
5);
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);
CX_TEST_ASSERT(begin == &nodes[
3]);
CX_TEST_ASSERT(end == &nodes[
2]);
CX_TEST_ASSERT(nodes[
0].prev == &nodes[
4]);
CX_TEST_ASSERT(nodes[
3].prev ==
NULL);
CX_TEST_ASSERT(nodes[
4].next == &nodes[
0]);
}
}
CX_TEST(test_linked_list_insert_sorted) {
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 {
node new_node = {
0};
new_node.data =
5;
cx_linked_list_insert_sorted(
&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]);
node new_begin = {
0};
new_begin.data =
1;
cx_linked_list_insert_sorted(
&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]);
node new_begin_dup = {
0};
new_begin_dup.data =
1;
cx_linked_list_insert_sorted(
&begin, &end,
loc_prev, loc_next,
&new_begin_dup, test_cmp_node
);
CX_TEST_ASSERT(new_begin_dup.prev == &new_begin);
CX_TEST_ASSERT(new_begin_dup.next == &nodes[
0]);
CX_TEST_ASSERT(nodes[
0].prev == &new_begin_dup);
CX_TEST_ASSERT(new_begin.next == &new_begin_dup);
CX_TEST_ASSERT(begin == &new_begin);
CX_TEST_ASSERT(end == &nodes[
4]);
node chain_start = {
NULL,
NULL,
8};
node chain_mid = {
NULL,
NULL,
14};
node chain_end = {
NULL,
NULL,
17};
cx_linked_list_link(&chain_start, &chain_mid, loc_prev, loc_next);
cx_linked_list_link(&chain_mid, &chain_end, loc_prev, loc_next);
cx_linked_list_insert_sorted_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_mid.prev == &nodes[
3]);
CX_TEST_ASSERT(chain_mid.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);
}
}
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 {
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]);
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]);
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]);
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]);
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);
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;
CX_TEST_DO {
CX_TEST_ASSERT(begin == cx_linked_list_first(testdata, loc_prev));
CX_TEST_ASSERT(begin == cx_linked_list_first(testdata->next, loc_prev));
CX_TEST_ASSERT(begin == cx_linked_list_first(testdata->next->next, loc_prev));
}
destroy_nodes_test_data(testdata);
}
CX_TEST(test_linked_list_last) {
node *testdata = create_nodes_test_data(
3);
void *end = testdata->next->next;
CX_TEST_DO {
CX_TEST_ASSERT(end == cx_linked_list_last(testdata, loc_next));
CX_TEST_ASSERT(end == cx_linked_list_last(testdata->next, loc_next));
CX_TEST_ASSERT(end == cx_linked_list_last(testdata->next->next, loc_next));
}
destroy_nodes_test_data(testdata);
}
CX_TEST(test_linked_list_prev) {
node *testdata = create_nodes_test_data(
3);
CX_TEST_DO {
CX_TEST_ASSERT(cx_linked_list_prev(testdata, loc_next, testdata) ==
NULL);
CX_TEST_ASSERT(cx_linked_list_prev(testdata, loc_next, testdata->next) == testdata);
CX_TEST_ASSERT(cx_linked_list_prev(testdata, loc_next, testdata->next->next) == testdata->next);
}
destroy_nodes_test_data(testdata);
}
CX_TEST(test_linked_list_remove) {
node *testdata = create_nodes_test_data(
3);
assign_nodes_test_data(testdata,
2,
4,
6);
node *first = testdata;
node *second = first->next;
node *third = second->next;
void *begin = testdata;
void *end = third;
CX_TEST_DO {
cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second);
CX_TEST_ASSERT(begin == first);
CX_TEST_ASSERT(end == third);
CX_TEST_ASSERT(first->prev ==
NULL);
CX_TEST_ASSERT(first->next == third);
CX_TEST_ASSERT(third->prev == first);
CX_TEST_ASSERT(third->next ==
NULL);
cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third);
CX_TEST_ASSERT(begin == first);
CX_TEST_ASSERT(end == first);
CX_TEST_ASSERT(first->prev ==
NULL);
CX_TEST_ASSERT(first->next ==
NULL);
cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first);
CX_TEST_ASSERT(begin ==
NULL);
CX_TEST_ASSERT(end ==
NULL);
}
free(first);
free(second);
free(third);
}
CX_TEST(test_linked_list_remove_chain) {
node *testdata = create_nodes_test_data(
5);
assign_nodes_test_data(testdata,
2,
4,
6,
8,
10);
void *begin = testdata;
void *end = cx_linked_list_last(testdata, loc_next);
void *orig_end = end;
node *kill_list[
5];
kill_list[
0] = testdata;
for (
unsigned i =
1 ; i <
5 ; i++) {
kill_list[i] = kill_list[i
-1]->next;
}
CX_TEST_DO {
size_t result = cx_linked_list_remove_chain(
&begin, &end,
-1, loc_next,
cx_linked_list_at(begin,
0, loc_next,
2),
2
);
CX_TEST_ASSERT(result ==
2);
CX_TEST_ASSERT(begin == testdata);
CX_TEST_ASSERT(end == orig_end);
node *new_idx2 = cx_linked_list_at(begin,
0, loc_next,
2);
CX_TEST_ASSERT(new_idx2->data ==
10);
CX_TEST_ASSERT(new_idx2->next ==
NULL);
CX_TEST_ASSERT(new_idx2->prev->data ==
8);
result = cx_linked_list_remove_chain(
&begin, &end,
-1, loc_next,
cx_linked_list_at(begin,
0, loc_next,
2),
2
);
CX_TEST_ASSERT(result ==
1);
CX_TEST_ASSERT(begin == testdata);
CX_TEST_ASSERT(end == testdata->next);
CX_TEST_ASSERT(
NULL == testdata->next->next);
}
for (
unsigned i =
0 ; i <
5 ; i++) {
free(kill_list[i]);
}
}
CX_TEST(test_linked_list_size) {
node *td5 = create_nodes_test_data(
5);
node *td13 = create_nodes_test_data(
13);
CX_TEST_DO {
CX_TEST_ASSERT(cx_linked_list_size(
NULL, loc_next) ==
0);
CX_TEST_ASSERT(cx_linked_list_size(td5, loc_next) ==
5);
CX_TEST_ASSERT(cx_linked_list_size(td13, loc_next) ==
13);
}
destroy_nodes_test_data(td5);
destroy_nodes_test_data(td13);
}
CX_TEST(test_linked_list_sort_empty) {
void *begin =
NULL;
CX_TEST_DO {
cx_linked_list_sort(&begin,
NULL, loc_prev, loc_next, loc_data, cx_cmp_int);
CX_TEST_ASSERT(true);
}
}
CX_TEST(test_linked_list_sort) {
const size_t len =
1500;
int *testdata = int_test_data(len);
void *scrambled = create_nodes_test_data(len);
node *n = scrambled;
for (
size_t i =
0; i < len; i++) {
n->data = testdata[i];
n = n->next;
}
int *sorted = malloc(len*
sizeof(
int));
memcpy(sorted, testdata, len*
sizeof(
int));
qsort(sorted, len,
sizeof(
int), cx_cmp_int);
void *begin = scrambled;
void *end = cx_linked_list_last(begin, loc_next);
CX_TEST_DO {
cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, cx_cmp_int);
node *check = begin;
node *check_last =
NULL;
for (
size_t i =
0; i < len; i++) {
CX_TEST_ASSERT(check->data == sorted[i]);
CX_TEST_ASSERT(check->prev == check_last);
if (i < len -
1) {
CX_TEST_ASSERT(check->next !=
NULL);
}
check_last = check;
check = check->next;
}
CX_TEST_ASSERT(check ==
NULL);
CX_TEST_ASSERT(end == check_last);
}
destroy_nodes_test_data(begin);
free(sorted);
free(testdata);
}
CX_TEST(test_linked_list_reverse) {
void *testdata = create_nodes_test_data(
4);
void *expected = create_nodes_test_data(
4);
assign_nodes_test_data(testdata,
2,
4,
6,
8);
assign_nodes_test_data(expected,
8,
6,
4,
2);
void *begin = testdata;
CX_TEST_DO {
void *end = cx_linked_list_last(begin, loc_next);
void *orig_begin = begin, *orig_end = end;
cx_linked_list_reverse(&begin, &end, loc_prev, loc_next);
CX_TEST_ASSERT(end == orig_begin);
CX_TEST_ASSERT(begin == orig_end);
CX_TEST_ASSERT(
0 == cx_linked_list_compare(begin, expected, loc_next, loc_data, cx_cmp_int));
}
destroy_nodes_test_data(begin);
destroy_nodes_test_data(expected);
}
CX_TEST(test_empty_list_size) {
CX_TEST_DO {
CX_TEST_ASSERT(cxEmptyList->collection.size ==
0);
CX_TEST_ASSERT(cxListSize(cxEmptyList) ==
0);
}
}
CX_TEST(test_empty_list_iterator) {
CxList *list = cxEmptyList;
CxIterator it1 = cxListIterator(list);
CxIterator it2 = cxListBackwardsIterator(list);
CX_TEST_DO {
CX_TEST_ASSERT(!cxIteratorValid(it1));
CX_TEST_ASSERT(!cxIteratorValid(it2));
int c =
0;
cx_foreach(
void*, data, it1) c++;
cx_foreach(
void*, data, it2) c++;
CX_TEST_ASSERT(c ==
0);
}
}
CX_TEST(test_null_list_iterator) {
CxList *list =
NULL;
CxIterator it1 = cxListIterator(list);
CxIterator it2 = cxListBackwardsIterator(list);
CxIterator it3 = cxListIteratorAt(list,
0);
CxIterator it4 = cxListBackwardsIteratorAt(list,
0);
CX_TEST_DO {
CX_TEST_ASSERT(!cxIteratorValid(it1));
CX_TEST_ASSERT(!cxIteratorValid(it2));
CX_TEST_ASSERT(!cxIteratorValid(it3));
CX_TEST_ASSERT(!cxIteratorValid(it4));
int c =
0;
cx_foreach(
void*, data, it1) c++;
cx_foreach(
void*, data, it2) c++;
cx_foreach(
void*, data, it3) c++;
cx_foreach(
void*, data, it4) c++;
CX_TEST_ASSERT(c ==
0);
}
}
CX_TEST(test_empty_list_noops) {
CX_TEST_DO {
CxList copy = *cxEmptyList;
cxListSort(cxEmptyList);
cxListClear(cxEmptyList);
cxListFree(cxEmptyList);
CX_TEST_ASSERT(
0 == memcmp(©, cxEmptyList,
sizeof(CxList)));
}
}
CX_TEST(test_empty_list_at) {
CX_TEST_DO {
CX_TEST_ASSERT(cxListAt(cxEmptyList,
0) ==
NULL);
CX_TEST_ASSERT(cxListAt(cxEmptyList,
1) ==
NULL);
CxList *list = cxLinkedListCreateSimple(
sizeof(
int));
CX_TEST_ASSERT(cxListAt(list,
0) ==
NULL);
CX_TEST_ASSERT(cxListAt(list,
1) ==
NULL);
cxListFree(list);
}
}
CX_TEST(test_empty_list_find) {
int x =
42, y =
1337;
CX_TEST_DO {
CX_TEST_ASSERT(cxListFind(cxEmptyList, &x) ==
0);
CX_TEST_ASSERT(cxListFindRemove(cxEmptyList, &y) ==
0);
CxList *list = cxLinkedListCreateSimple(
sizeof(
int));
CX_TEST_ASSERT(cxListFind(list, &x) ==
0);
CX_TEST_ASSERT(cxListFindRemove(list, &y) ==
0);
cxListFree(list);
}
}
CX_TEST(test_empty_list_compare) {
CxList *empty = cxEmptyList;
CxList *ll = cxLinkedListCreateSimple(
sizeof(
int));
CxList *al = cxArrayListCreateSimple(
sizeof(
int),
8);
int x =
5;
CX_TEST_DO {
CX_TEST_ASSERT(
0 == cxListCompare(empty, cxEmptyList));
CX_TEST_ASSERT(
0 == cxListCompare(ll, cxEmptyList));
CX_TEST_ASSERT(
0 == cxListCompare(al, cxEmptyList));
CX_TEST_ASSERT(
0 == cxListCompare(cxEmptyList, ll));
CX_TEST_ASSERT(
0 == cxListCompare(cxEmptyList, al));
cxListAdd(ll, &x);
cxListAdd(al, &x);
CX_TEST_ASSERT(
0 < cxListCompare(ll, cxEmptyList));
CX_TEST_ASSERT(
0 < cxListCompare(al, cxEmptyList));
CX_TEST_ASSERT(
0 > cxListCompare(cxEmptyList, ll));
CX_TEST_ASSERT(
0 > cxListCompare(cxEmptyList, al));
}
cxListFree(ll);
cxListFree(al);
}
CX_TEST(test_null_list_free) {
CX_TEST_DO {
cxListFree(
NULL);
}
}
CX_TEST(test_list_ll_create) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxList *list = cxLinkedListCreate(alloc, cx_cmp_int,
sizeof(
int));
CX_TEST_ASSERT(list !=
NULL);
CX_TEST_ASSERT(list->collection.elem_size ==
sizeof(
int));
CX_TEST_ASSERT(list->collection.simple_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.advanced_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.destructor_data ==
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(list->collection.allocator == alloc);
CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_int);
CX_TEST_ASSERT(!list->collection.store_pointer);
cxListFree(list);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_ll_create_simple) {
CxList *list = cxLinkedListCreateSimple(
sizeof(
int));
CX_TEST_DO {
CX_TEST_ASSERT(list !=
NULL);
CX_TEST_ASSERT(list->collection.elem_size ==
sizeof(
int));
CX_TEST_ASSERT(list->collection.simple_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.advanced_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.destructor_data ==
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
CX_TEST_ASSERT(list->collection.cmpfunc ==
NULL);
CX_TEST_ASSERT(!list->collection.store_pointer);
}
cxListFree(list);
}
CX_TEST(test_list_ll_create_simple_for_pointers) {
CxList *list = cxLinkedListCreateSimple(
CX_STORE_POINTERS);
CX_TEST_DO {
CX_TEST_ASSERT(list !=
NULL);
CX_TEST_ASSERT(list->collection.elem_size ==
sizeof(
void*));
CX_TEST_ASSERT(list->collection.simple_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.advanced_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.destructor_data ==
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_ptr);
CX_TEST_ASSERT(list->collection.store_pointer);
}
cxListFree(list);
}
CX_TEST(test_list_arl_create) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxList *list = cxArrayListCreate(alloc, cx_cmp_int,
sizeof(
int),
8);
CX_TEST_ASSERT(list !=
NULL);
CX_TEST_ASSERT(list->collection.elem_size ==
sizeof(
int));
CX_TEST_ASSERT(list->collection.simple_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.advanced_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.destructor_data ==
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(list->collection.allocator == alloc);
CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_int);
CX_TEST_ASSERT(!list->collection.store_pointer);
cxListFree(list);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_arl_create_simple) {
CxList *list = cxArrayListCreateSimple(
sizeof(
int),
8);
CX_TEST_DO {
CX_TEST_ASSERT(list !=
NULL);
CX_TEST_ASSERT(list->collection.elem_size ==
sizeof(
int));
CX_TEST_ASSERT(list->collection.simple_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.advanced_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.destructor_data ==
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
CX_TEST_ASSERT(list->collection.cmpfunc ==
NULL);
CX_TEST_ASSERT(!list->collection.store_pointer);
}
cxListFree(list);
}
CX_TEST(test_list_arl_create_simple_for_pointers) {
CxList *list = cxArrayListCreateSimple(
CX_STORE_POINTERS,
8);
CX_TEST_DO {
CX_TEST_ASSERT(list !=
NULL);
CX_TEST_ASSERT(list->collection.elem_size ==
sizeof(
void*));
CX_TEST_ASSERT(list->collection.simple_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.advanced_destructor ==
NULL);
CX_TEST_ASSERT(list->collection.destructor_data ==
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_ptr);
CX_TEST_ASSERT(list->collection.store_pointer);
}
cxListFree(list);
}
static void test_fake_simple_int_destr(
void *elem) {
*(
int *) elem =
42;
}
CX_TEST(test_list_pll_destroy_no_destr) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
void *item = cxMalloc(alloc,
sizeof(
int));
CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS);
cxListAdd(list, item);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxListFree(list);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxFree(alloc, item);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_pll_destroy_simple_destr) {
CX_TEST_DO {
int item =
0;
CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS);
list->collection.simple_destructor = test_fake_simple_int_destr;
cxListAdd(list, &item);
cxListFree(list);
CX_TEST_ASSERT(item ==
42);
}
}
CX_TEST(test_list_pll_destroy_adv_destr) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
void *item = cxMalloc(alloc,
sizeof(
int));
CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS);
list->collection.destructor_data = alloc;
list->collection.advanced_destructor = (cx_destructor_func2) cxFree;
cxListAdd(list, item);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxListFree(list);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_parl_destroy_no_destr) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
void *item = cxMalloc(alloc,
sizeof(
int));
CxList *list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS,
4);
cxListAdd(list, item);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxListFree(list);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxFree(alloc, item);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_parl_destroy_simple_destr) {
CX_TEST_DO {
int item =
0;
CxList *list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS,
4);
list->collection.simple_destructor = test_fake_simple_int_destr;
cxListAdd(list, &item);
cxListFree(list);
CX_TEST_ASSERT(item ==
42);
}
}
CX_TEST(test_list_parl_destroy_adv_destr) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
void *item = cxMalloc(alloc,
sizeof(
int));
CxList *list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS,
4);
list->collection.destructor_data = alloc;
list->collection.advanced_destructor = (cx_destructor_func2) cxFree;
cxListAdd(list, item);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxListFree(list);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
#define set_up_combo \
CxTestingAllocator talloc; \
cx_testing_allocator_init(&talloc); \
CxAllocator *alloc = &talloc.base; \
CX_TEST_DO {
#define tear_down_combo \
cxListFree(list); \
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));\
} \
cx_testing_allocator_destroy(&talloc);
#define roll_out_test_invokers(name) \
CX_TEST(test_list_ll_##name) { \
set_up_combo \
CxList *list = cxLinkedListCreate(alloc, cx_cmp_int,
sizeof(
int)); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, false); \
tear_down_combo \
} \
CX_TEST(test_list_arl_##name) { \
set_up_combo \
CxList *list = cxArrayListCreate(alloc, cx_cmp_int,
sizeof(
int),
8); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, false); \
tear_down_combo \
} \
CX_TEST(test_list_kvl_##name) { \
set_up_combo \
CxList *list = cxKvListCreate(alloc, cx_cmp_int,
sizeof(
int)); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, false); \
tear_down_combo \
} \
CX_TEST(test_list_pll_##name) { \
set_up_combo \
CxList *list = cxLinkedListCreate(alloc, cx_cmp_int,
CX_STORE_POINTERS); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, true); \
tear_down_combo \
} \
CX_TEST(test_list_parl_##name) { \
set_up_combo \
CxList *list = cxArrayListCreate(alloc, cx_cmp_int,
CX_STORE_POINTERS,
8); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, true); \
tear_down_combo \
} \
CX_TEST(test_list_pkvl_##name) { \
set_up_combo \
CxList *list = cxKvListCreate(alloc, cx_cmp_int,
CX_STORE_POINTERS); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, true); \
tear_down_combo \
}
#define roll_out_test_combos(name, body) \
static CX_TEST_SUBROUTINE(test_list_verify_##name, CxList *list, \
cx_attr_unused bool isptrlist) body \
roll_out_test_invokers(name)
static void set_default_class_funcs(CxList *list, cx_list_class *defaulted_cl) {
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;
defaulted_cl->compare =
NULL;
if (list->climpl ==
NULL) {
list->cl = defaulted_cl;
}
else {
list->climpl = defaulted_cl;
}
}
#define do_set_default_class_funcs(list) \
cx_list_class defaulted_cl; \
set_default_class_funcs(list, &defaulted_cl)
#define roll_out_test_combos_with_defaulted_funcs(name, body) \
static CX_TEST_SUBROUTINE(test_list_verify_##name, CxList *list, \
cx_attr_unused bool isptrlist) body \
roll_out_test_invokers(name) \
CX_TEST(test_list_llm_##name) { \
set_up_combo \
CxList *list = cxLinkedListCreate(alloc, cx_cmp_int,
sizeof(
int)); \
do_set_default_class_funcs(list); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, false); \
tear_down_combo \
} \
CX_TEST(test_list_arlm_##name) { \
set_up_combo \
CxList *list = cxArrayListCreate(alloc, cx_cmp_int,
sizeof(
int),
8); \
do_set_default_class_funcs(list); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, false); \
tear_down_combo \
} \
CX_TEST(test_list_pllm_##name) { \
set_up_combo \
CxList *list = cxLinkedListCreate(alloc, cx_cmp_int,
CX_STORE_POINTERS); \
do_set_default_class_funcs(list); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, true); \
tear_down_combo \
} \
CX_TEST(test_list_parlm_##name) { \
set_up_combo \
CxList *list = cxArrayListCreate(alloc, cx_cmp_int,
CX_STORE_POINTERS,
8); \
do_set_default_class_funcs(list); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_##name, list, true); \
tear_down_combo \
}
#define array_init(...) {
__VA_ARGS__}
static inline
int *int_test_data_added_to_list(CxList *list, bool isptrlist,
size_t len) {
int *testdata = int_test_data(len);
if (isptrlist) {
for (
size_t i =
0; i < len; i++) {
cxListAdd(list, &testdata[i]);
}
}
else {
cxListAddArray(list, testdata, len);
}
return testdata;
}
roll_out_test_combos(add, {
const size_t len =
250;
int *testdata = int_test_data(len);
for (
size_t i =
0; i < len; i++) {
CX_TEST_ASSERT(cxListAdd(list, &testdata[i]) ==
0);
}
CX_TEST_ASSERT(cxListSize(list) == len);
for (
size_t i =
0; i < len; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == testdata[i]);
}
for (
size_t i =
0; i < len; i++) {
++testdata[i];
}
if (isptrlist) {
for (
size_t i =
0; i < len; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == testdata[i]);
}
}
else {
for (
size_t i =
0; i < len; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == testdata[i] -
1);
}
}
free(testdata);
})
roll_out_test_combos(insert, {
int a =
5;
int b =
47;
int c =
13;
int d =
42;
CX_TEST_ASSERT(cxListInsert(list,
1, &a) !=
0);
CX_TEST_ASSERT(cxListSize(list) ==
0);
CX_TEST_ASSERT(cxListInsert(list,
0, &a) ==
0);
CX_TEST_ASSERT(cxListSize(list) ==
1);
CX_TEST_ASSERT(cxListInsert(list,
0, &b) ==
0);
CX_TEST_ASSERT(cxListSize(list) ==
2);
CX_TEST_ASSERT(cxListInsert(list,
1, &c) ==
0);
CX_TEST_ASSERT(cxListSize(list) ==
3);
CX_TEST_ASSERT(cxListInsert(list,
3, &d) ==
0);
CX_TEST_ASSERT(cxListSize(list) ==
4);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
13);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
42);
})
roll_out_test_combos(emplace, {
if (isptrlist) {
int **x;
int y =
5;
int z =
7;
int w =
13;
x = cxListEmplace(list);
CX_TEST_ASSERT(x !=
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
1);
*x = &y;
CX_TEST_ASSERT(*(
int*)cxListAt(list,
0) ==
5);
x = cxListEmplace(list);
CX_TEST_ASSERT(x !=
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
2);
*x = &z;
CX_TEST_ASSERT(*(
int*)cxListAt(list,
1) ==
7);
CX_TEST_ASSERT(
NULL == cxListEmplaceAt(list,
3));
CX_TEST_ASSERT(cxListSize(list) ==
2);
x = cxListEmplaceAt(list,
1);
CX_TEST_ASSERT(x !=
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
3);
*x = &w;
CX_TEST_ASSERT(*(
int*)cxListAt(list,
0) ==
5);
CX_TEST_ASSERT(*(
int*)cxListAt(list,
1) ==
13);
CX_TEST_ASSERT(*(
int*)cxListAt(list,
2) ==
7);
}
else {
int *x;
x = cxListEmplace(list);
CX_TEST_ASSERT(x !=
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
1);
*x =
5;
CX_TEST_ASSERT(*(
int*)cxListAt(list,
0) ==
5);
x = cxListEmplace(list);
CX_TEST_ASSERT(x !=
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
2);
*x =
7;
CX_TEST_ASSERT(*(
int*)cxListAt(list,
1) ==
7);
CX_TEST_ASSERT(
NULL == cxListEmplaceAt(list,
3));
CX_TEST_ASSERT(cxListSize(list) ==
2);
x = cxListEmplaceAt(list,
1);
CX_TEST_ASSERT(x !=
NULL);
CX_TEST_ASSERT(cxListSize(list) ==
3);
*x =
13;
CX_TEST_ASSERT(*(
int*)cxListAt(list,
0) ==
5);
CX_TEST_ASSERT(*(
int*)cxListAt(list,
1) ==
13);
CX_TEST_ASSERT(*(
int*)cxListAt(list,
2) ==
7);
}
})
roll_out_test_combos_with_defaulted_funcs(insert_array, {
int a[
5] = array_init(
5,
47,
11,
13,
42);
int b[
5] = array_init(
9,
18,
72,
50,
7);
int *aptr[
5];
int *bptr[
5];
for (
size_t i =
0; i <
5; i++) {
aptr[i] = &a[i];
bptr[i] = &b[i];
}
size_t inserted;
if (isptrlist) {
inserted = cxListInsertArray(list,
0, aptr,
5);
}
else {
inserted = cxListInsertArray(list,
0, a,
5);
}
CX_TEST_ASSERT(inserted ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) ==
11);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
13);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
4) ==
42);
if (isptrlist) {
inserted = cxListInsertArray(list,
3, bptr,
5);
}
else {
inserted = cxListInsertArray(list,
3, b,
5);
}
CX_TEST_ASSERT(inserted ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) ==
11);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
9);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
4) ==
18);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
5) ==
72);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
6) ==
50);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
7) ==
7);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
8) ==
13);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
9) ==
42);
})
roll_out_test_combos_with_defaulted_funcs(emplace_array, {
int a[
5] = array_init(
5,
47,
11,
13,
42);
int b[
5] = array_init(
9,
18,
72,
50,
7);
CxIterator iter;
iter = cxListEmplaceArray(list,
5);
CX_TEST_ASSERT(cxListSize(list) ==
5);
CX_TEST_ASSERT(iter.elem_count ==
5);
CX_TEST_ASSERT(iter.index ==
0);
if (isptrlist) {
cx_foreach(
int **, elem, iter) {
*elem = a + iter.index;
}
}
else {
cx_foreach(
int *, elem, iter) {
*elem = a[iter.index];
}
}
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) ==
11);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
13);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
4) ==
42);
iter = cxListEmplaceArrayAt(list,
3,
5);
CX_TEST_ASSERT(cxListSize(list) ==
10);
CX_TEST_ASSERT(iter.elem_count ==
5);
CX_TEST_ASSERT(iter.index ==
0);
if (isptrlist) {
cx_foreach(
int **, elem, iter) {
*elem = b + iter.index;
}
}
else {
cx_foreach(
int *, elem, iter) {
*elem = b[iter.index];
}
}
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) ==
5);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) ==
11);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
9);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
4) ==
18);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
5) ==
72);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
6) ==
50);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
7) ==
7);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
8) ==
13);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
9) ==
42);
})
roll_out_test_combos_with_defaulted_funcs(insert_sorted, {
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[
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));
CX_TEST_ASSERT(
0 == cxListInsertSorted(list, &d2));
CX_TEST_ASSERT(
0 == cxListInsertSorted(list, &d3));
CX_TEST_ASSERT(
0 == cxListInsertSorted(list, &d4));
CX_TEST_ASSERT(
0 == cxListInsertSorted(list, &d5));
if (isptrlist) {
inserted = cxListInsertSortedArray(list, d6ptr,
6);
}
else {
inserted = cxListInsertSortedArray(list, d6a,
6);
}
CX_TEST_ASSERT(inserted ==
6);
if (isptrlist) {
inserted = cxListInsertSortedArray(list, d7ptr,
6);
}
else {
inserted = cxListInsertSortedArray(list, d7a,
6);
}
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]);
}
})
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[
8] = array_init(
52,
54,
56,
56,
62,
62,
64,
75);
int d7a[
8] = array_init(
51,
51,
57,
58,
65,
77,
78,
78);
int d8 =
90;
int d9 =
56;
int d10a[
5] = array_init(
58,
58,
67,
75,
90);
int *d6ptr[
8];
int *d7ptr[
8];
int *d10ptr[
5];
for (
size_t i =
0; i <
8; i++) {
d6ptr[i] = &d6a[i];
d7ptr[i] = &d7a[i];
}
for (
size_t i =
0 ; i <
5 ; i++) {
d10ptr[i] = &d10a[i];
}
size_t processed;
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) {
processed = cxListInsertUniqueArray(list, d6ptr,
8);
}
else {
processed = cxListInsertUniqueArray(list, d6a,
8);
}
CX_TEST_ASSERT(processed ==
8);
if (isptrlist) {
processed = cxListInsertUniqueArray(list, d7ptr,
8);
}
else {
processed = cxListInsertUniqueArray(list, d7a,
8);
}
CX_TEST_ASSERT(processed ==
8);
CX_TEST_ASSERT(
0 == cxListInsertUnique(list, &d8));
CX_TEST_ASSERT(
0 == cxListInsertUnique(list, &d9));
if (isptrlist) {
processed = cxListInsertUniqueArray(list, d10ptr,
5);
}
else {
processed = cxListInsertUniqueArray(list, d10a,
5);
}
CX_TEST_ASSERT(processed ==
5);
CX_TEST_ASSERT(cxListSize(list) ==
19);
for (
size_t i =
0; i <
19; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == expected[i]);
}
})
roll_out_test_combos_with_defaulted_funcs(insert_unique_not_sorted, {
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(
50,
80,
60,
40,
70,
52,
54,
56,
62,
64,
75,
51,
57,
58,
65,
77,
78,
90,
67
);
CX_TEST_ASSERT(
0 == cxListAdd(list, &d1));
CX_TEST_ASSERT(
0 == cxListAdd(list, &d2));
CX_TEST_ASSERT(
0 == cxListAdd(list, &d3));
CX_TEST_ASSERT(
0 == cxListAdd(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]);
}
})
roll_out_test_combos(remove, {
const size_t testdata_len =
32;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
CX_TEST_ASSERT(cxListRemove(list,
2) ==
0);
CX_TEST_ASSERT(cxListRemove(list,
4) ==
0);
CX_TEST_ASSERT(cxListSize(list) == testdata_len -
2);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) == testdata[
0]);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) == testdata[
1]);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) == testdata[
3]);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) == testdata[
4]);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
4) == testdata[
6]);
CX_TEST_ASSERT(cxListRemove(list,
0) ==
0);
CX_TEST_ASSERT(cxListSize(list) == testdata_len -
3);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) == testdata[
1]);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) == testdata[
3]);
CX_TEST_ASSERT(cxListRemove(list, testdata_len) !=
0);
free(testdata);
})
roll_out_test_combos(remove_and_get, {
int testdata[
10];
for (
unsigned i =
0 ; i <
10 ; i++) {
testdata[i] =
2*i;
cxListAdd(list, &testdata[i]);
}
if (isptrlist) {
int *x;
CX_TEST_ASSERT(cxListPop(list, &x) ==
0);
CX_TEST_ASSERT(*x ==
18);
CX_TEST_ASSERT(cxListPop(list, &x) ==
0);
CX_TEST_ASSERT(*x ==
16);
CX_TEST_ASSERT(cxListPopFront(list, &x) ==
0);
CX_TEST_ASSERT(*x ==
0);
CX_TEST_ASSERT(cxListPopFront(list, &x) ==
0);
CX_TEST_ASSERT(*x ==
2);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
3, &x) ==
0);
CX_TEST_ASSERT(*x ==
10);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
3, &x) ==
0);
CX_TEST_ASSERT(*x ==
12);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
8, &x) !=
0);
CX_TEST_ASSERT(*x ==
12);
*x =
1337;
cxListClear(list);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
0, &x) !=
0);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
1, &x) !=
0);
CX_TEST_ASSERT(cxListPop(list, &x) !=
0);
CX_TEST_ASSERT(cxListPopFront(list, &x) !=
0);
CX_TEST_ASSERT(*x ==
1337);
}
else {
int x;
CX_TEST_ASSERT(cxListPop(list, &x) ==
0);
CX_TEST_ASSERT(x ==
18);
CX_TEST_ASSERT(cxListPop(list, &x) ==
0);
CX_TEST_ASSERT(x ==
16);
CX_TEST_ASSERT(cxListPopFront(list, &x) ==
0);
CX_TEST_ASSERT(x ==
0);
CX_TEST_ASSERT(cxListPopFront(list, &x) ==
0);
CX_TEST_ASSERT(x ==
2);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
3, &x) ==
0);
CX_TEST_ASSERT(x ==
10);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
3, &x) ==
0);
CX_TEST_ASSERT(x ==
12);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
8, &x) !=
0);
CX_TEST_ASSERT(x ==
12);
x =
1337;
cxListClear(list);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
0, &x) !=
0);
CX_TEST_ASSERT(cxListRemoveAndGet(list,
1, &x) !=
0);
CX_TEST_ASSERT(cxListPop(list, &x) !=
0);
CX_TEST_ASSERT(cxListPopFront(list, &x) !=
0);
CX_TEST_ASSERT(x ==
1337);
}
})
static unsigned test_remove_array_destr_ctr;
static void test_remove_array_destr(cx_attr_unused
void *d) {
test_remove_array_destr_ctr++;
}
roll_out_test_combos(remove_array, {
const size_t testdata_len =
32;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
cxDefineDestructor(list, test_remove_array_destr);
test_remove_array_destr_ctr =
0;
int targete[
8];
int *targetp[
8];
memset(targete,
0,
sizeof(targete));
memset(targetp,
0,
sizeof(targetp));
void *target = isptrlist ? (
void*) targetp : targete;
CX_TEST_ASSERT(
8 == cxListRemoveArrayAndGet(list,
8,
8, target));
CX_TEST_ASSERT(
0 == test_remove_array_destr_ctr);
CX_TEST_ASSERT(
24 == cxListSize(list));
for (
unsigned int i =
0 ; i <
8 ; i++) {
CX_TEST_ASSERT((*(
int*)cxListAt(list, i)) == testdata[i]);
}
for (
unsigned int i =
8 ; i <
24 ; i++) {
CX_TEST_ASSERT((*(
int*)cxListAt(list, i)) == testdata[
8+i]);
}
for (
unsigned int i =
0 ; i <
8 ; i++) {
if (isptrlist) {
CX_TEST_ASSERT(targetp[i] == &testdata[
8 + i]);
}
else {
CX_TEST_ASSERT(targete[i] == testdata[
8 + i]);
}
}
CX_TEST_ASSERT(
8 == cxListRemoveArray(list,
8,
8));
CX_TEST_ASSERT(
8 == test_remove_array_destr_ctr);
CX_TEST_ASSERT(
16 == cxListSize(list));
for (
unsigned int i =
0 ; i <
8 ; i++) {
CX_TEST_ASSERT((*(
int*)cxListAt(list, i)) == testdata[i]);
}
for (
unsigned int i =
8 ; i <
16 ; i++) {
CX_TEST_ASSERT((*(
int*)cxListAt(list, i)) == testdata[
16+i]);
}
test_remove_array_destr_ctr =
0;
memset(targete,
0,
sizeof(targete));
memset(targetp,
0,
sizeof(targetp));
CX_TEST_ASSERT(
4 == cxListRemoveArrayAndGet(list,
12,
8, target));
CX_TEST_ASSERT(
0 == test_remove_array_destr_ctr);
CX_TEST_ASSERT(
12 == cxListSize(list));
for (
unsigned int i =
0 ; i <
8 ; i++) {
CX_TEST_ASSERT((*(
int*)cxListAt(list, i)) == testdata[i]);
}
for (
unsigned int i =
8 ; i <
12 ; i++) {
CX_TEST_ASSERT((*(
int*)cxListAt(list, i)) == testdata[
16+i]);
}
for (
unsigned int i =
0 ; i <
4 ; i++) {
if (isptrlist) {
CX_TEST_ASSERT(targetp[i] == &testdata[
28 + i]);
}
else {
CX_TEST_ASSERT(targete[i] == testdata[
28 + i]);
}
}
for (
unsigned int i =
4 ; i <
8 ; i++) {
if (isptrlist) {
CX_TEST_ASSERT(targetp[i] ==
NULL);
}
else {
CX_TEST_ASSERT(targete[i] ==
0);
}
}
free(testdata);
})
roll_out_test_combos(find_remove, {
const size_t testdata_len =
250;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
unsigned exp = rand() % testdata_len;
int val = testdata[exp];
for (
unsigned i =
0 ; i < exp ; i++) {
if (testdata[i] == val) {
exp = i;
break;
}
}
CX_TEST_ASSERT(cxListSize(list) == testdata_len);
CX_TEST_ASSERT(cxListFind(list, &val) == exp);
CX_TEST_ASSERT(cxListFindRemove(list, &val) == exp);
CX_TEST_ASSERT(cxListSize(list) == testdata_len -
1);
CX_TEST_ASSERT(cxListFind(list, &val) != exp);
int notinlist =
-1;
CX_TEST_ASSERT(cxListFindRemove(list, ¬inlist) == cxListSize(list));
CX_TEST_ASSERT(cxListSize(list) == testdata_len -
1);
free(testdata);
})
roll_out_test_combos(find_remove_sorted, {
const size_t testdata_len =
250;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
qsort(testdata, testdata_len,
sizeof(
int), cx_cmp_int);
cxListSort(list);
unsigned exp = rand() % testdata_len;
int val = testdata[exp];
for (
unsigned i =
0 ; i < exp ; i++) {
if (testdata[i] == val) {
exp = i;
break;
}
}
CX_TEST_ASSERT(cxListSize(list) == testdata_len);
CX_TEST_ASSERT(cxListFind(list, &val) == exp);
CX_TEST_ASSERT(cxListFindRemove(list, &val) == exp);
CX_TEST_ASSERT(cxListSize(list) == testdata_len -
1);
CX_TEST_ASSERT(cxListFind(list, &val) != exp);
int notinlist =
-1;
CX_TEST_ASSERT(cxListFindRemove(list, ¬inlist) == cxListSize(list));
CX_TEST_ASSERT(cxListSize(list) == testdata_len -
1);
free(testdata);
})
roll_out_test_combos(contains, {
int a =
37;
int b =
42;
int c =
55;
cxListAdd(list, &a);
cxListAdd(list, &b);
cxListAdd(list, &c);
int x;
x =
37;
CX_TEST_ASSERT(cxListContains(list, &x));
x =
42;
CX_TEST_ASSERT(cxListContains(list, &x));
x =
55;
CX_TEST_ASSERT(cxListContains(list, &x));
x =
47;
CX_TEST_ASSERT(!cxListContains(list, &x));
})
roll_out_test_combos(clear, {
int *testdata = int_test_data_added_to_list(list, isptrlist,
8);
CX_TEST_ASSERT(cxListSize(list) >
0);
cxListClear(list);
CX_TEST_ASSERT(cxListSize(list) ==
0);
free(testdata);
})
roll_out_test_combos(at, {
size_t len =
128;
int *testdata = int_test_data_added_to_list(list, isptrlist,
128);
CX_TEST_ASSERT(cxListSize(list) == len);
for (
size_t i =
0; i < len; i++) {
CX_TEST_ASSERT(cxListIndexValid(list, i));
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == testdata[i]);
}
CX_TEST_ASSERT(!cxListIndexValid(list, len));
CX_TEST_ASSERT(cxListAt(list, len) ==
NULL);
free(testdata);
})
roll_out_test_combos(set, {
int v1 =
42;
cxListAdd(list, &v1);
int v2 =
100;
cxListAdd(list, &v2);
int v3 =
47;
cxListAdd(list, &v3);
int v1new =
99;
CX_TEST_ASSERT(cxListSet(list,
0, &v1new) ==
0);
CX_TEST_ASSERT(*(
int *) cxListFirst(list) ==
99);
int v3new =
101;
CX_TEST_ASSERT(cxListSet(list,
2, &v3new) ==
0);
CX_TEST_ASSERT(*(
int *) cxListLast(list) ==
101);
int oob =
1337;
CX_TEST_ASSERT(cxListSet(list,
3, &oob) !=
0);
})
roll_out_test_combos_with_defaulted_funcs(swap, {
int original[
16] = array_init(
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15);
int swapped[
16] = array_init(
8,
4,
14,
3,
1,
5,
9,
12,
0,
6,
11,
10,
7,
15,
2,
13);
for (
size_t i =
0; i <
16; i++) {
cxListAdd(list, &original[i]);
}
CX_TEST_ASSERT(
0 == cxListSwap(list,
1,
4));
CX_TEST_ASSERT(
0 == cxListSwap(list,
2,
14));
CX_TEST_ASSERT(
0 == cxListSwap(list,
9,
6));
CX_TEST_ASSERT(
0 == cxListSwap(list,
3,
3));
CX_TEST_ASSERT(
0 == cxListSwap(list,
10,
11));
CX_TEST_ASSERT(
0 == cxListSwap(list,
8,
0));
CX_TEST_ASSERT(
0 == cxListSwap(list,
7,
12));
CX_TEST_ASSERT(
0 == cxListSwap(list,
13,
15));
CX_TEST_ASSERT(
0 != cxListSwap(list,
5,
16));
CX_TEST_ASSERT(
0 != cxListSwap(list,
16,
6));
CX_TEST_ASSERT(
0 != cxListSwap(list,
16,
17));
CxIterator iter = cxListIterator(list);
cx_foreach(
int*, e, iter) {
CX_TEST_ASSERT(*e == swapped[iter.index]);
}
iter = cxListBackwardsIterator(list);
cx_foreach(
int*, e, iter) {
CX_TEST_ASSERT(*e == swapped[iter.index]);
}
})
CX_TEST(test_list_arl_swap_no_sbo) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
size_t item_size =
2*cx_array_swap_sbo_size;
CxList *list = cxArrayListCreate(alloc, cx_cmp_int, item_size,
8);
char *obj = malloc(item_size);
for (
char c =
'a' ; c <=
'z' ; c++) {
obj[
0] = c;
obj[item_size
-1] = c;
cxListAdd(list, obj);
}
free(obj);
CX_TEST_ASSERT(((
char*)cxListAt(list,
3))[
0] ==
'd');
CX_TEST_ASSERT(((
char*)cxListAt(list,
17))[
0] ==
'r');
CX_TEST_ASSERT(((
char*)cxListAt(list,
3))[item_size
-1] ==
'd');
CX_TEST_ASSERT(((
char*)cxListAt(list,
17))[item_size
-1] ==
'r');
cxListSwap(list,
3,
17);
CX_TEST_ASSERT(((
char*)cxListAt(list,
17))[
0] ==
'd');
CX_TEST_ASSERT(((
char*)cxListAt(list,
3))[
0] ==
'r');
CX_TEST_ASSERT(((
char*)cxListAt(list,
17))[item_size
-1] ==
'd');
CX_TEST_ASSERT(((
char*)cxListAt(list,
3))[item_size
-1] ==
'r');
cxListFree(list);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
roll_out_test_combos(find, {
const size_t testdata_len =
500;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
for (
size_t attempt =
0; attempt <
25; attempt++) {
unsigned exp = rand() % testdata_len;
int val = testdata[exp];
for (
unsigned i =
0 ; i < exp ; i++) {
if (testdata[i] == val) {
exp = i;
break;
}
}
CX_TEST_ASSERT(cxListFind(list, &val) == exp);
}
int notinlist =
-1;
CX_TEST_ASSERT(cxListFind(list, ¬inlist) == cxListSize(list));
free(testdata);
})
roll_out_test_combos_with_defaulted_funcs(sort, {
const size_t testdata_len =
250;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
int *expected = malloc(testdata_len*
sizeof(
int));
memcpy(expected, testdata, testdata_len*
sizeof(
int));
qsort(expected, testdata_len,
sizeof(
int), cx_cmp_int);
cxListSort(list);
for (
size_t i =
0; i < testdata_len; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == expected[i]);
}
free(expected);
free(testdata);
})
roll_out_test_combos(reverse, {
const size_t testdata_len =
50;
int *testdata = int_test_data_added_to_list(list, isptrlist, testdata_len);
cxListReverse(list);
for (
size_t i =
0; i < testdata_len; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, i) == testdata[testdata_len -
1 - i]);
}
free(testdata);
})
roll_out_test_combos(iterator, {
const size_t len =
50;
int *testdata = int_test_data_added_to_list(list, isptrlist, len);
CxIterator iter = cxListIterator(list);
CX_TEST_ASSERT(iter.elem_size == list->collection.elem_size);
CX_TEST_ASSERT(iter.elem_count == list->collection.size);
size_t i =
0;
cx_foreach(
int*, x, iter) {
CX_TEST_ASSERT(i == iter.index);
CX_TEST_ASSERT(*x == testdata[iter.index]);
i++;
}
CX_TEST_ASSERT(i == cxListSize(list));
iter = cxListBackwardsIterator(list);
cx_foreach(
int*, x, iter) {
CX_TEST_ASSERT(i -
1 == iter.index);
CX_TEST_ASSERT(*x == testdata[iter.index]);
i--;
}
CX_TEST_ASSERT(i ==
0);
i = len /
2;
CxIterator mut_iter = cxListIteratorAt(list, i);
CX_TEST_ASSERT(mut_iter.elem_size == list->collection.elem_size);
CX_TEST_ASSERT(mut_iter.elem_count == list->collection.size);
size_t j =
0;
cx_foreach(
int*, x, mut_iter) {
CX_TEST_ASSERT(mut_iter.index == len /
2 + j /
2);
CX_TEST_ASSERT(*x == testdata[i]);
if (i %
2 ==
1) cxIteratorFlagRemoval(mut_iter);
i++;
j++;
}
CX_TEST_ASSERT(i == len);
i = len /
2;
j =
0;
mut_iter = cxListBackwardsIteratorAt(list, i -
1);
cx_foreach(
int*, x, mut_iter) {
CX_TEST_ASSERT(mut_iter.index == len /
2 -
1 - j);
CX_TEST_ASSERT(*x == testdata[i -
1]);
if (i %
2 ==
0) cxIteratorFlagRemoval(mut_iter);
i--;
j++;
}
CX_TEST_ASSERT(i ==
0);
CX_TEST_ASSERT(cxListSize(list) == len /
2);
CX_TEST_ASSERT(mut_iter.elem_count == len /
2);
for (
size_t k =
0; k < len /
2; k++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, k) == testdata[k *
2]);
}
free(testdata);
})
roll_out_test_combos(insert_with_iterator, {
int fivenums[] = array_init(
0,
1,
2,
3,
4);
for (
size_t i =
0; i <
5; i++) {
cxListAdd(list, &fivenums[i]);
}
int newdata[] = array_init(
10,
20,
30,
40,
50);
CxIterator iter = cxListIteratorAt(list,
2);
CX_TEST_ASSERT(cxIteratorValid(iter));
CX_TEST_ASSERT(iter.index ==
2);
CX_TEST_ASSERT(*(
int *) cxIteratorCurrent(iter) ==
2);
CX_TEST_ASSERT(iter.elem_count ==
5);
cxListInsertAfter(&iter, &newdata[
0]);
CX_TEST_ASSERT(cxIteratorValid(iter));
CX_TEST_ASSERT(iter.index ==
2);
CX_TEST_ASSERT(*(
int *) cxIteratorCurrent(iter) ==
2);
CX_TEST_ASSERT(iter.elem_count ==
6);
cxListInsertBefore(&iter, &newdata[
1]);
CX_TEST_ASSERT(cxIteratorValid(iter));
CX_TEST_ASSERT(iter.index ==
3);
CX_TEST_ASSERT(*(
int *) cxIteratorCurrent(iter) ==
2);
CX_TEST_ASSERT(iter.elem_count ==
7);
iter = cxListIterator(list);
cxListInsertBefore(&iter, &newdata[
2]);
CX_TEST_ASSERT(cxIteratorValid(iter));
CX_TEST_ASSERT(iter.index ==
1);
CX_TEST_ASSERT(*(
int *) cxIteratorCurrent(iter) ==
0);
CX_TEST_ASSERT(iter.elem_count ==
8);
iter = cxListIteratorAt(list, cxListSize(list));
cxListInsertBefore(&iter, &newdata[
3]);
CX_TEST_ASSERT(!cxIteratorValid(iter));
CX_TEST_ASSERT(iter.index ==
9);
CX_TEST_ASSERT(iter.elem_count ==
9);
iter = cxListIteratorAt(list, cxListSize(list));
cxListInsertAfter(&iter, &newdata[
4]);
CX_TEST_ASSERT(!cxIteratorValid(iter));
CX_TEST_ASSERT(iter.index ==
10);
CX_TEST_ASSERT(iter.elem_count ==
10);
int expdata[] = array_init(
30,
0,
1,
20,
2,
10,
3,
4,
40,
50);
for (
size_t j =
0; j <
10; j++) {
CX_TEST_ASSERT(*(
int *) cxListAt(list, j) == expdata[j]);
}
})
static CX_TEST_SUBROUTINE(test_list_verify_compare, CxList *left, CxList *right) {
CX_TEST_ASSERTM(cxListCompare(left, right) ==
0,
"lists don''t start identical");
int x =
42;
cxListAdd(left, &x);
CX_TEST_ASSERT(cxListSize(left) > cxListSize(right));
CX_TEST_ASSERT(cxListCompare(left, right) >
0);
CX_TEST_ASSERT(cxListCompare(right, left) <
0);
cxListAdd(right, &x);
CX_TEST_ASSERT(cxListSize(left) == cxListSize(right));
CX_TEST_ASSERT(cxListCompare(left, right) ==
0);
int a =
5, b =
10;
cxListInsert(left,
15, &a);
cxListInsert(right,
15, &b);
CX_TEST_ASSERT(cxListSize(left) == cxListSize(right));
CX_TEST_ASSERT(cxListCompare(left, right) <
0);
CX_TEST_ASSERT(cxListCompare(right, left) >
0);
*(
int *) cxListAt(left,
15) =
10;
CX_TEST_ASSERT(cxListCompare(left, right) ==
0);
}
#define roll_out_compare_tests(suffix, otherctr) \
roll_out_test_combos(compare_##suffix, { \
const size_t len =
47; \
int *testdata = int_test_data_added_to_list(list, isptrlist, len); \
CxList *other = otherctr; \
for (
size_t i =
0; i < len; i++) cxListAdd(other, &testdata[i]); \
CX_TEST_CALL_SUBROUTINE(test_list_verify_compare, list, other); \
cxListFree(other); \
free(testdata); \
})
roll_out_compare_tests(
ll, cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int))
)
roll_out_compare_tests(
pll, cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS)
)
roll_out_compare_tests(
arl, cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
50)
)
roll_out_compare_tests(
parl, cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS,
50)
)
roll_out_test_combos_with_defaulted_funcs(compare_unoptimized, {
const size_t len =
33;
int *testdata = int_test_data_added_to_list(list, isptrlist, len);
CxList *other = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
50);
do_set_default_class_funcs(other);
for (
size_t i =
0; i < len; i++) cxListAdd(other, &testdata[i]);
CX_TEST_CALL_SUBROUTINE(test_list_verify_compare, list, other);
cxListFree(other);
free(testdata);
})
static unsigned destr_test_ctr;
static int destr_last_value;
static void simple_destr_test_fun(
void *data) {
int *ptr = data;
destr_last_value = *ptr;
*ptr = destr_last_value +
1;
destr_test_ctr++;
}
static void advanced_destr_test_fun(cx_attr_unused
void *u,
void *data) {
simple_destr_test_fun(data);
}
static CX_TEST_SUBROUTINE(test_list_verify_destructor, CxList *list,
const int *testdata,
size_t testdata_len) {
destr_test_ctr =
0;
int off = list->collection.store_pointer ?
1 :
0;
cxListRemove(list,
15);
CX_TEST_ASSERT(
1 == destr_test_ctr);
CX_TEST_ASSERT(testdata[
15] == destr_last_value + off);
CX_TEST_ASSERT(testdata_len - destr_test_ctr == cxListSize(list));
cxListRemove(list,
47);
CX_TEST_ASSERT(
2 == destr_test_ctr);
CX_TEST_ASSERT(testdata[
48] == destr_last_value + off);
CX_TEST_ASSERT(testdata_len - destr_test_ctr == cxListSize(list));
CxIterator iter = cxListIteratorAt(list,
7);
CX_TEST_ASSERT(iter.elem_count == testdata_len -
2);
cxIteratorNext(iter);
CX_TEST_ASSERT(
2 == destr_test_ctr);
CX_TEST_ASSERT(testdata[
48] == destr_last_value + off);
CX_TEST_ASSERT(testdata_len - destr_test_ctr == cxListSize(list));
cxIteratorFlagRemoval(iter);
cxIteratorNext(iter);
CX_TEST_ASSERT(iter.elem_count == testdata_len -
3);
CX_TEST_ASSERT(
3 == destr_test_ctr);
CX_TEST_ASSERT(testdata[
8] == destr_last_value + off);
CX_TEST_ASSERT(testdata_len - destr_test_ctr == cxListSize(list));
iter = cxListBackwardsIteratorAt(list,
5);
cxIteratorNext(iter);
CX_TEST_ASSERT(
3 == destr_test_ctr);
CX_TEST_ASSERT(testdata[
8] == destr_last_value + off);
CX_TEST_ASSERT(testdata_len - destr_test_ctr == cxListSize(list));
cxIteratorFlagRemoval(iter);
cxIteratorNext(iter);
CX_TEST_ASSERT(iter.elem_count == testdata_len -
4);
CX_TEST_ASSERT(
4 == destr_test_ctr);
CX_TEST_ASSERT(testdata[
4] == destr_last_value + off);
CX_TEST_ASSERT(testdata_len - destr_test_ctr == cxListSize(list));
cxListClear(list);
CX_TEST_ASSERT(testdata_len == destr_test_ctr);
CX_TEST_ASSERT(testdata[testdata_len -
1] == destr_last_value + off);
}
roll_out_test_combos(simple_destr, {
const size_t len =
60;
int *testdata = int_test_data_added_to_list(list, isptrlist, len);
cxDefineDestructor(list, simple_destr_test_fun);
CX_TEST_CALL_SUBROUTINE(test_list_verify_destructor, list, testdata, len);
free(testdata);
})
roll_out_test_combos(advanced_destr, {
const size_t len =
75;
int *testdata = int_test_data_added_to_list(list, isptrlist, len);
cxDefineAdvancedDestructor(list, advanced_destr_test_fun,
NULL);
CX_TEST_CALL_SUBROUTINE(test_list_verify_destructor, list, testdata, len);
free(testdata);
})
roll_out_test_combos(reserve_and_shrink, {
int *td1 = int_test_data_added_to_list(list, isptrlist,
500);
CX_TEST_ASSERT(
0 == cxListReserve(list,
200));
CX_TEST_ASSERT(
0 == cxListReserve(list,
1000));
int *td2 = int_test_data_added_to_list(list, isptrlist,
500);
int *td3 = int_test_data_added_to_list(list, isptrlist,
500);
CX_TEST_ASSERT(
0 == cxListShrink(list));
size_t i =
0;
for (
size_t j =
0 ; j <
500 ; j++, i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(list, i) == td1[j]);
}
for (
size_t j =
0 ; j <
500 ; j++, i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(list, i) == td2[j]);
}
for (
size_t j =
0 ; j <
500 ; j++, i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(list, i) == td3[j]);
}
free(td1);
free(td2);
free(td3);
})
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_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)++;
return dest;
}
static CX_TEST_SUBROUTINE(verify_clone, CxList *target, CxList *source, bool target_isptrlist) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *testing_alloc = &talloc.base;
if (target_isptrlist) {
cxDefineAdvancedDestructor(target, cxFree, testing_alloc);
}
int source_data[
8] = array_init(
1,
2,
3,
4,
5,
6,
7,
8);
for (
unsigned i =
0 ; i <
8 ; i++) {
cxListAdd(source, &source_data[i]);
}
int initial_data[
4] = array_init(
1,
2,
3,
4);
for (
unsigned i =
0; i <
4; i++) {
if (target_isptrlist) {
int *x = cxMalloc(testing_alloc,
sizeof(
int));
*x = initial_data[i];
cxListAdd(target, x);
}
else {
cxListAdd(target, &initial_data[i]);
}
}
int expected_data[
12] = array_init(
1,
2,
3,
4,
1,
3,
5,
7,
9,
11,
13,
15);
int c =
0;
CX_TEST_ASSERT(
0 == cxListClone(target, source, test_clone_func, testing_alloc, &c));
CX_TEST_ASSERT(c ==
8);
CX_TEST_ASSERT(cxListSize(target) ==
12);
CX_TEST_ASSERT(cxListSize(source) ==
8);
for (
unsigned i =
0 ; i <
12 ; i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(target, i) == expected_data[i]);
}
for (
unsigned i =
0 ; i <
8 ; i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(source, i) == source_data[i]);
}
cxListFree(target);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
cx_testing_allocator_destroy(&talloc);
}
static CX_TEST_SUBROUTINE(verify_clone_alloc_fail, CxList *target, CxList *source, bool target_isptrlist) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *testing_alloc = &talloc.base;
if (target_isptrlist) {
cxDefineAdvancedDestructor(target, cxFree, testing_alloc);
}
int source_data[
8] = array_init(
1,
2,
3,
4,
5,
6,
7,
8);
for (
unsigned i =
0 ; i <
8 ; i++) {
cxListAdd(source, &source_data[i]);
}
int initial_data[
4] = array_init(
1,
2,
3,
4);
for (
unsigned i =
0; i <
4; i++) {
if (target_isptrlist) {
int *x = cxMalloc(testing_alloc,
sizeof(
int));
*x = initial_data[i];
cxListAdd(target, x);
}
else {
cxListAdd(target, &initial_data[i]);
}
}
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);
for (
unsigned i =
0 ; i <
9 ; i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(target, i) == expected_data[i]);
}
for (
unsigned i =
0 ; i <
8 ; i++) {
CX_TEST_ASSERT(*(
int*)cxListAt(source, i) == source_data[i]);
}
cxListFree(target);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
cx_testing_allocator_destroy(&talloc);
}
roll_out_test_combos(clone_into_arl, {
CxList *target = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
8);
CX_TEST_CALL_SUBROUTINE(verify_clone, target, list, false);
})
roll_out_test_combos(clone_into_ll, {
CxList *target = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
CX_TEST_CALL_SUBROUTINE(verify_clone, target, list, false);
})
roll_out_test_combos(clone_into_parl, {
CxList *target = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS,
8);
CX_TEST_CALL_SUBROUTINE(verify_clone, target, list, true);
})
roll_out_test_combos(clone_into_pll, {
CxList *target = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS);
CX_TEST_CALL_SUBROUTINE(verify_clone, target, list, true);
})
roll_out_test_combos(clone_alloc_fail_into_arl, {
CxList *target = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
8);
CX_TEST_CALL_SUBROUTINE(verify_clone_alloc_fail, target, list, false);
})
roll_out_test_combos(clone_alloc_fail_into_ll, {
CxList *target = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
CX_TEST_CALL_SUBROUTINE(verify_clone_alloc_fail, target, list, false);
})
roll_out_test_combos(clone_alloc_fail_into_parl, {
CxList *target = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS,
8);
CX_TEST_CALL_SUBROUTINE(verify_clone_alloc_fail, target, list, true);
})
roll_out_test_combos(clone_alloc_fail_into_pll, {
CxList *target = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS);
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};
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
};
for (
unsigned i =
0 ; i < cx_nmemb(dst_data) ; i++) {
int *x = cxMalloc(&talloc.base,
sizeof(
int));
*x = dst_data[i];
cxListAdd(dst, x);
}
cxListAddArray(minuend, minuend_data,
50);
cxListAddArray(subtrahend, subtrahend_data,
50);
if (sorted) {
cxListSort(dst);
cxListSort(minuend);
cxListSort(subtrahend);
}
size_t expected_len =
40;
int expected_unsorted[] = {
47,
178,
176,
83,
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[] = {
47,
83,
176,
178,
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 =
34;
}
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_testing_allocator_destroy(&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);
}
}
static CX_TEST_SUBROUTINE(verify_intersection, 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 *src = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
CxList *other = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
int dst_data[] = {
47,
178,
176,
83};
int src_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 other_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
};
for (
unsigned i =
0 ; i < cx_nmemb(dst_data) ; i++) {
int *x = cxMalloc(&talloc.base,
sizeof(
int));
*x = dst_data[i];
cxListAdd(dst, x);
}
cxListAddArray(src, src_data,
50);
cxListAddArray(other, other_data,
50);
if (sorted) {
cxListSort(dst);
cxListSort(src);
cxListSort(other);
}
size_t expected_len =
18;
int expected_unsorted[] = {
47,
178,
176,
83,
130,
27,
161,
71,
53,
199,
151,
176,
49,
85,
198,
188,
63,
41
};
int expected_sorted[] = {
47,
83,
176,
178,
27,
41,
49,
53,
63,
71,
85,
130,
151,
161,
176,
188,
198,
199
};
if (alloc_fail) {
test_clone_func_max_enabled = true;
test_clone_func_max_clones =
10;
expected_len =
14;
}
CxList *expected = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int), expected_len);
cxListAddArray(expected, sorted ? expected_sorted : expected_unsorted, expected_len);
int result = cxListIntersection(dst, src, other, 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(src);
cxListFree(other);
cxListFree(expected);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_intersection_unsorted) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_intersection, false, false);
}
}
CX_TEST(test_list_intersection_sorted) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_intersection, true, false);
}
}
CX_TEST(test_list_intersection_unsorted_alloc_fail) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_intersection, false, true);
}
}
CX_TEST(test_list_intersection_sorted_alloc_fail) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_intersection, true, true);
}
}
static CX_TEST_SUBROUTINE(verify_union, 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 *src = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
CxList *other = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
int dst_data[] = {
47,
178,
176,
83};
int src_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 other_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
};
for (
unsigned i =
0 ; i < cx_nmemb(dst_data) ; i++) {
int *x = cxMalloc(&talloc.base,
sizeof(
int));
*x = dst_data[i];
cxListAdd(dst, x);
}
cxListAddArray(src, src_data,
50);
cxListAddArray(other, other_data,
50);
if (sorted) {
cxListSort(dst);
cxListSort(src);
cxListSort(other);
}
size_t expected_len =
90;
int expected_unsorted[] = {
47,
178,
176,
83,
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,
75,
137,
111,
197,
141,
46,
103,
69,
146,
79,
154,
45,
38,
139,
193,
90,
64,
142,
115,
120,
78,
100,
101,
42,
21,
1,
10,
114,
181,
178,
136,
59,
73,
99,
144,
118
};
int expected_sorted[] = {
47,
83,
176,
178,
1,
4,
9,
10,
12,
20,
21,
27,
28,
29,
32,
33,
37,
38,
41,
42,
44,
45,
46,
49,
51,
53,
54,
59,
63,
64,
65,
69,
70,
71,
73,
74,
75,
76,
77,
78,
79,
83,
85,
88,
90,
92,
94,
97,
99,
100,
101,
103,
106,
109,
111,
114,
115,
116,
118,
120,
124,
129,
130,
136,
137,
139,
141,
142,
144,
146,
150,
151,
153,
154,
161,
162,
171,
173,
175,
176,
177,
178,
181,
188,
193,
194,
197,
198,
199,
200
};
if (alloc_fail) {
test_clone_func_max_enabled = true;
test_clone_func_max_clones =
66;
expected_len =
70;
}
CxList *expected = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int), expected_len);
cxListAddArray(expected, sorted ? expected_sorted : expected_unsorted, expected_len);
int result = cxListUnion(dst, src, other, 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(src);
cxListFree(other);
cxListFree(expected);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_list_union_unsorted) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_union, false, false);
}
}
CX_TEST(test_list_union_sorted) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_union, true, false);
}
}
CX_TEST(test_list_union_unsorted_alloc_fail) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_union, false, true);
}
}
CX_TEST(test_list_union_sorted_alloc_fail) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(verify_union, true, true);
}
}
CX_TEST(test_list_simple_clones) {
int a[] = {
1,
2,
5,
8,
10};
int b[] = {
1,
3,
5,
7,
9,
11};
int c[] = {
2,
4,
6,
8,
10,
12};
int d[] = {
4,
8,
12};
CxList *la = cxArrayListCreateSimple(
sizeof(
int),
8);
cxCollectionCompareFunc(la, cx_cmp_int);
cxListInsertSortedArray(la, a, cx_nmemb(a));
CxList *lb = cxArrayListCreateSimple(
sizeof(
int),
8);
cxCollectionCompareFunc(lb, cx_cmp_int);
cxListInsertSortedArray(lb, b, cx_nmemb(b));
CxList *lc = cxArrayListCreateSimple(
sizeof(
int),
8);
cxCollectionCompareFunc(lc, cx_cmp_int);
cxListInsertSortedArray(lc, c, cx_nmemb(c));
CxList *ld = cxArrayListCreateSimple(
sizeof(
int),
8);
cxCollectionCompareFunc(ld, cx_cmp_int);
cxListInsertSortedArray(ld, d, cx_nmemb(d));
CxList *d1 = cxArrayListCreateSimple(
sizeof(
int),
8);
cxCollectionCompareFunc(d1, cx_cmp_int);
CxList *d2 = cxArrayListCreateSimple(
sizeof(
int),
8);
cxCollectionCompareFunc(d2, cx_cmp_int);
CX_TEST_DO {
CX_TEST_ASSERT(
0 == cxListCloneSimple(d1, la));
CX_TEST_ASSERT(
0 == cxListCompare(d1, la));
CX_TEST_ASSERT(cxCollectionSorted(d1));
CX_TEST_ASSERT(
0 == cxListUnionSimple(d2, d1, lb));
CX_TEST_ASSERT(cxCollectionSorted(d2));
CxList *expected_union = cxArrayListCreateSimple(
sizeof(
int),
8);
{
int expected[] = {
1,
2,
3,
5,
7,
8,
9,
10,
11};
cxListAddArray(expected_union, expected, cx_nmemb(expected));
}
CX_TEST_ASSERT(
0 == cxListCompare(d2, expected_union));
cxListFree(expected_union);
cxListClear(d1);
CX_TEST_ASSERT(
0 == cxListIntersectionSimple(d1, d2, lc));
CX_TEST_ASSERT(cxCollectionSorted(d1));
CxList *expected_intersection = cxArrayListCreateSimple(
sizeof(
int),
8);
{
int expected[] = {
2,
8,
10};
cxListAddArray(expected_intersection, expected, cx_nmemb(expected));
}
CX_TEST_ASSERT(
0 == cxListCompare(d1, expected_intersection));
cxListFree(expected_intersection);
cxListClear(d2);
CX_TEST_ASSERT(
0 == cxListDifferenceSimple(d2, d1, ld));
CX_TEST_ASSERT(cxCollectionSorted(d2));
CxList *expected_difference = cxArrayListCreateSimple(
sizeof(
int),
8);
{
int expected[] = {
2,
10};
cxListAddArray(expected_difference, expected, cx_nmemb(expected));
}
CX_TEST_ASSERT(
0 == cxListCompare(d2, expected_difference));
cxListFree(expected_difference);
}
cxListFree(d1);
cxListFree(d2);
cxListFree(la);
cxListFree(lb);
cxListFree(lc);
cxListFree(ld);
}
CX_TEST(test_list_pointer_list_supports_null) {
CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
CX_STORE_POINTERS);
int x =
47;
int y =
11;
int z =
1337;
int *nptr =
NULL;
cxListAdd(list, &x);
cxListAdd(list, &y);
cxListAdd(list, nptr);
cxListAdd(list, &z);
CX_TEST_DO {
CX_TEST_ASSERT(cxListSize(list) ==
4);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
0) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
11);
CX_TEST_ASSERT((
int *) cxListAt(list,
2) ==
NULL);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
1337);
CX_TEST_ASSERT(cxListFind(list, nptr) ==
2);
cxListSort(list);
CX_TEST_ASSERT((
int *) cxListAt(list,
0) ==
NULL);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
1) ==
11);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
2) ==
47);
CX_TEST_ASSERT(*(
int *) cxListAt(list,
3) ==
1337);
}
cxListFree(list);
}
CX_TEST(test_list_use_insert_unique_to_remove_duplicates) {
CxList *linked_list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
CxList *array_list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
8);
CxList *defaulted_list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
8);
do_set_default_class_funcs(defaulted_list);
int test_array[
23] = {
120,
-13,
100,
-90,
13,
-56,
74,
20,
28,
80,
18,
-56,
130,
12,
15,
0,
39,
100,
0,
29,
28,
85,
20
};
int test_array_unique[
18] = {
-90,
-56,
-13,
0,
12,
13,
15,
18,
20,
28,
29,
39,
74,
80,
85,
100,
120,
130
};
CX_TEST_DO {
qsort(test_array,
23,
sizeof(
int), cx_cmp_int);
cxListInsertUniqueArray(linked_list, test_array,
23);
cxListInsertUniqueArray(array_list, test_array,
23);
cxListInsertUniqueArray(defaulted_list, test_array,
23);
CX_TEST_ASSERT(cxListSize(linked_list) ==
18);
CX_TEST_ASSERT(cxListSize(array_list) ==
18);
CX_TEST_ASSERT(cxListSize(defaulted_list) ==
18);
for (
unsigned i =
0; i <
18; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(linked_list, i) == test_array_unique[i]);
CX_TEST_ASSERT(*(
int *) cxListAt(array_list, i) == test_array_unique[i]);
CX_TEST_ASSERT(*(
int *) cxListAt(defaulted_list, i) == test_array_unique[i]);
}
}
cxListFree(defaulted_list);
cxListFree(linked_list);
cxListFree(array_list);
}
CX_TEST(test_list_use_insert_unique_with_duplicates_in_source) {
CxList *linked_list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int));
CxList *array_list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
8);
CxList *defaulted_list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int,
sizeof(
int),
8);
do_set_default_class_funcs(defaulted_list);
int pre_filled[
10] = {
-13,
5,
18,
30,
40,
45,
50,
80,
85,
110};
cxListInsertSortedArray(linked_list, pre_filled,
10);
cxListInsertSortedArray(array_list, pre_filled,
10);
cxListInsertSortedArray(defaulted_list, pre_filled,
10);
int test_array[
23] = {
120,
-13,
100,
-90,
13,
-56,
74,
20,
28,
80,
18,
-56,
130,
12,
15,
0,
39,
100,
0,
29,
28,
85,
20
};
int test_array_unique[
24] = {
-90,
-56,
-13,
0,
5,
12,
13,
15,
18,
20,
28,
29,
30,
39,
40,
45,
50,
74,
80,
85,
100,
110,
120,
130
};
CX_TEST_DO {
qsort(test_array,
23,
sizeof(
int), cx_cmp_int);
cxListInsertUniqueArray(linked_list, test_array,
23);
cxListInsertUniqueArray(array_list, test_array,
23);
cxListInsertUniqueArray(defaulted_list, test_array,
23);
CX_TEST_ASSERT(cxListSize(linked_list) ==
24);
CX_TEST_ASSERT(cxListSize(array_list) ==
24);
CX_TEST_ASSERT(cxListSize(defaulted_list) ==
24);
for (
unsigned i =
0; i <
24; i++) {
CX_TEST_ASSERT(*(
int *) cxListAt(linked_list, i) == test_array_unique[i]);
CX_TEST_ASSERT(*(
int *) cxListAt(array_list, i) == test_array_unique[i]);
CX_TEST_ASSERT(*(
int *) cxListAt(defaulted_list, i) == test_array_unique[i]);
}
CX_TEST_ASSERT(*(
int*)cxListLast(linked_list) ==
130);
CX_TEST_ASSERT(*(
int*)cxListLast(array_list) ==
130);
CX_TEST_ASSERT(*(
int*)cxListLast(defaulted_list) ==
130);
}
cxListFree(defaulted_list);
cxListFree(linked_list);
cxListFree(array_list);
}
CxTestSuite *cx_test_suite_array_list(
void) {
CxTestSuite *suite = cx_test_suite_new(
"array_list");
cx_test_register(suite, test_array_add);
cx_test_register(suite, test_array_add8);
cx_test_register(suite, test_array_add16);
cx_test_register(suite, test_array_copy_unsupported_width);
cx_test_register(suite, test_array_copy_overlap);
cx_test_register(suite, test_array_reserve);
cx_test_register(suite, test_array_reserve_unsupported_width);
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_array_binary_search_with_duplicates);
cx_test_register(suite, test_list_arl_create);
cx_test_register(suite, test_list_arl_create_simple);
cx_test_register(suite, test_list_arl_create_simple_for_pointers);
cx_test_register(suite, test_list_parl_destroy_no_destr);
cx_test_register(suite, test_list_parl_destroy_simple_destr);
cx_test_register(suite, test_list_parl_destroy_adv_destr);
cx_test_register(suite, test_list_arl_add);
cx_test_register(suite, test_list_parl_add);
cx_test_register(suite, test_list_arl_insert);
cx_test_register(suite, test_list_parl_insert);
cx_test_register(suite, test_list_arl_emplace);
cx_test_register(suite, test_list_parl_emplace);
cx_test_register(suite, test_list_arl_insert_array);
cx_test_register(suite, test_list_parl_insert_array);
cx_test_register(suite, test_list_arl_emplace_array);
cx_test_register(suite, test_list_parl_emplace_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_insert_unique_not_sorted);
cx_test_register(suite, test_list_parl_insert_unique_not_sorted);
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);
cx_test_register(suite, test_list_parl_remove_and_get);
cx_test_register(suite, test_list_arl_remove_array);
cx_test_register(suite, test_list_parl_remove_array);
cx_test_register(suite, test_list_arl_find_remove);
cx_test_register(suite, test_list_parl_find_remove);
cx_test_register(suite, test_list_arl_find_remove_sorted);
cx_test_register(suite, test_list_parl_find_remove_sorted);
cx_test_register(suite, test_list_arl_contains);
cx_test_register(suite, test_list_parl_contains);
cx_test_register(suite, test_list_arl_clear);
cx_test_register(suite, test_list_parl_clear);
cx_test_register(suite, test_list_arl_at);
cx_test_register(suite, test_list_parl_at);
cx_test_register(suite, test_list_arl_set);
cx_test_register(suite, test_list_parl_set);
cx_test_register(suite, test_list_arl_swap);
cx_test_register(suite, test_list_parl_swap);
cx_test_register(suite, test_list_arl_swap_no_sbo);
cx_test_register(suite, test_list_arl_find);
cx_test_register(suite, test_list_parl_find);
cx_test_register(suite, test_list_arl_sort);
cx_test_register(suite, test_list_parl_sort);
cx_test_register(suite, test_list_arl_reverse);
cx_test_register(suite, test_list_parl_reverse);
cx_test_register(suite, test_list_arl_iterator);
cx_test_register(suite, test_list_parl_iterator);
cx_test_register(suite, test_list_arl_insert_with_iterator);
cx_test_register(suite, test_list_parl_insert_with_iterator);
cx_test_register(suite, test_list_arl_compare_ll);
cx_test_register(suite, test_list_arl_compare_arl);
cx_test_register(suite, test_list_arl_compare_pll);
cx_test_register(suite, test_list_arl_compare_parl);
cx_test_register(suite, test_list_parl_compare_ll);
cx_test_register(suite, test_list_parl_compare_arl);
cx_test_register(suite, test_list_parl_compare_pll);
cx_test_register(suite, test_list_parl_compare_parl);
cx_test_register(suite, test_list_arl_simple_destr);
cx_test_register(suite, test_list_parl_simple_destr);
cx_test_register(suite, test_list_arl_advanced_destr);
cx_test_register(suite, test_list_parl_advanced_destr);
cx_test_register(suite, test_list_arl_reserve_and_shrink);
cx_test_register(suite, test_list_parl_reserve_and_shrink);
cx_test_register(suite, test_list_arl_clone_into_arl);
cx_test_register(suite, test_list_parl_clone_into_arl);
cx_test_register(suite, test_list_arl_clone_into_ll);
cx_test_register(suite, test_list_parl_clone_into_ll);
cx_test_register(suite, test_list_arl_clone_into_parl);
cx_test_register(suite, test_list_parl_clone_into_parl);
cx_test_register(suite, test_list_arl_clone_into_pll);
cx_test_register(suite, test_list_parl_clone_into_pll);
cx_test_register(suite, test_list_arl_clone_alloc_fail_into_arl);
cx_test_register(suite, test_list_parl_clone_alloc_fail_into_arl);
cx_test_register(suite, test_list_arl_clone_alloc_fail_into_ll);
cx_test_register(suite, test_list_parl_clone_alloc_fail_into_ll);
cx_test_register(suite, test_list_arl_clone_alloc_fail_into_parl);
cx_test_register(suite, test_list_parl_clone_alloc_fail_into_parl);
cx_test_register(suite, test_list_arl_clone_alloc_fail_into_pll);
cx_test_register(suite, test_list_parl_clone_alloc_fail_into_pll);
return suite;
}
CxTestSuite *cx_test_suite_array_list_defaulted_funcs(
void) {
CxTestSuite *suite = cx_test_suite_new(
"array_list with defaulted functions");
cx_test_register(suite, test_list_arlm_insert_array);
cx_test_register(suite, test_list_parlm_insert_array);
cx_test_register(suite, test_list_arlm_emplace_array);
cx_test_register(suite, test_list_parlm_emplace_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_insert_unique_not_sorted);
cx_test_register(suite, test_list_parlm_insert_unique_not_sorted);
cx_test_register(suite, test_list_arlm_swap);
cx_test_register(suite, test_list_parlm_swap);
cx_test_register(suite, test_list_arlm_sort);
cx_test_register(suite, test_list_parlm_sort);
cx_test_register(suite, test_list_arl_compare_unoptimized);
cx_test_register(suite, test_list_parl_compare_unoptimized);
cx_test_register(suite, test_list_arlm_compare_unoptimized);
cx_test_register(suite, test_list_parlm_compare_unoptimized);
return suite;
}
CxTestSuite *cx_test_suite_linked_list(
void) {
CxTestSuite *suite = cx_test_suite_new(
"linked_list");
cx_test_register(suite, test_linked_list_link_unlink);
cx_test_register(suite, test_linked_list_at);
cx_test_register(suite, test_linked_list_find);
cx_test_register(suite, test_linked_list_compare);
cx_test_register(suite, test_linked_list_add);
cx_test_register(suite, test_linked_list_prepend);
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);
cx_test_register(suite, test_linked_list_remove);
cx_test_register(suite, test_linked_list_remove_chain);
cx_test_register(suite, test_linked_list_size);
cx_test_register(suite, test_linked_list_sort_empty);
cx_test_register(suite, test_linked_list_sort);
cx_test_register(suite, test_linked_list_reverse);
cx_test_register(suite, test_list_ll_create);
cx_test_register(suite, test_list_ll_create_simple);
cx_test_register(suite, test_list_ll_create_simple_for_pointers);
cx_test_register(suite, test_list_pll_destroy_no_destr);
cx_test_register(suite, test_list_pll_destroy_simple_destr);
cx_test_register(suite, test_list_pll_destroy_adv_destr);
cx_test_register(suite, test_list_ll_add);
cx_test_register(suite, test_list_pll_add);
cx_test_register(suite, test_list_ll_insert);
cx_test_register(suite, test_list_pll_insert);
cx_test_register(suite, test_list_ll_emplace);
cx_test_register(suite, test_list_pll_emplace);
cx_test_register(suite, test_list_ll_insert_array);
cx_test_register(suite, test_list_pll_insert_array);
cx_test_register(suite, test_list_ll_emplace_array);
cx_test_register(suite, test_list_pll_emplace_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_insert_unique_not_sorted);
cx_test_register(suite, test_list_pll_insert_unique_not_sorted);
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);
cx_test_register(suite, test_list_pll_remove_and_get);
cx_test_register(suite, test_list_ll_remove_array);
cx_test_register(suite, test_list_pll_remove_array);
cx_test_register(suite, test_list_ll_find_remove);
cx_test_register(suite, test_list_pll_find_remove);
cx_test_register(suite, test_list_ll_find_remove_sorted);
cx_test_register(suite, test_list_pll_find_remove_sorted);
cx_test_register(suite, test_list_ll_contains);
cx_test_register(suite, test_list_pll_contains);
cx_test_register(suite, test_list_ll_clear);
cx_test_register(suite, test_list_pll_clear);
cx_test_register(suite, test_list_ll_at);
cx_test_register(suite, test_list_pll_at);
cx_test_register(suite, test_list_ll_set);
cx_test_register(suite, test_list_pll_set);
cx_test_register(suite, test_list_ll_swap);
cx_test_register(suite, test_list_pll_swap);
cx_test_register(suite, test_list_ll_find);
cx_test_register(suite, test_list_pll_find);
cx_test_register(suite, test_list_ll_sort);
cx_test_register(suite, test_list_pll_sort);
cx_test_register(suite, test_list_ll_reverse);
cx_test_register(suite, test_list_pll_reverse);
cx_test_register(suite, test_list_ll_iterator);
cx_test_register(suite, test_list_pll_iterator);
cx_test_register(suite, test_list_ll_insert_with_iterator);
cx_test_register(suite, test_list_pll_insert_with_iterator);
cx_test_register(suite, test_list_ll_compare_ll);
cx_test_register(suite, test_list_ll_compare_arl);
cx_test_register(suite, test_list_ll_compare_pll);
cx_test_register(suite, test_list_ll_compare_parl);
cx_test_register(suite, test_list_pll_compare_ll);
cx_test_register(suite, test_list_pll_compare_arl);
cx_test_register(suite, test_list_pll_compare_pll);
cx_test_register(suite, test_list_pll_compare_parl);
cx_test_register(suite, test_list_ll_simple_destr);
cx_test_register(suite, test_list_pll_simple_destr);
cx_test_register(suite, test_list_ll_advanced_destr);
cx_test_register(suite, test_list_pll_advanced_destr);
cx_test_register(suite, test_list_ll_reserve_and_shrink);
cx_test_register(suite, test_list_pll_reserve_and_shrink);
cx_test_register(suite, test_list_ll_clone_into_arl);
cx_test_register(suite, test_list_pll_clone_into_arl);
cx_test_register(suite, test_list_ll_clone_into_ll);
cx_test_register(suite, test_list_pll_clone_into_ll);
cx_test_register(suite, test_list_ll_clone_into_parl);
cx_test_register(suite, test_list_pll_clone_into_parl);
cx_test_register(suite, test_list_ll_clone_into_pll);
cx_test_register(suite, test_list_pll_clone_into_pll);
cx_test_register(suite, test_list_ll_clone_alloc_fail_into_arl);
cx_test_register(suite, test_list_pll_clone_alloc_fail_into_arl);
cx_test_register(suite, test_list_ll_clone_alloc_fail_into_ll);
cx_test_register(suite, test_list_pll_clone_alloc_fail_into_ll);
cx_test_register(suite, test_list_ll_clone_alloc_fail_into_parl);
cx_test_register(suite, test_list_pll_clone_alloc_fail_into_parl);
cx_test_register(suite, test_list_ll_clone_alloc_fail_into_pll);
cx_test_register(suite, test_list_pll_clone_alloc_fail_into_pll);
return suite;
}
CxTestSuite *cx_test_suite_linked_list_defaulted_funcs(
void) {
CxTestSuite *suite = cx_test_suite_new(
"linked_list with defaulted functions");
cx_test_register(suite, test_list_llm_insert_array);
cx_test_register(suite, test_list_pllm_insert_array);
cx_test_register(suite, test_list_llm_emplace_array);
cx_test_register(suite, test_list_pllm_emplace_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_insert_unique_not_sorted);
cx_test_register(suite, test_list_pllm_insert_unique_not_sorted);
cx_test_register(suite, test_list_llm_swap);
cx_test_register(suite, test_list_pllm_swap);
cx_test_register(suite, test_list_llm_sort);
cx_test_register(suite, test_list_pllm_sort);
cx_test_register(suite, test_list_ll_compare_unoptimized);
cx_test_register(suite, test_list_pll_compare_unoptimized);
cx_test_register(suite, test_list_llm_compare_unoptimized);
cx_test_register(suite, test_list_pllm_compare_unoptimized);
return suite;
}
CxTestSuite *cx_test_suite_kv_list(
void) {
CxTestSuite *suite = cx_test_suite_new(
"kv_list");
cx_test_register(suite, test_list_kvl_add);
cx_test_register(suite, test_list_pkvl_add);
cx_test_register(suite, test_list_kvl_insert);
cx_test_register(suite, test_list_pkvl_insert);
cx_test_register(suite, test_list_kvl_emplace);
cx_test_register(suite, test_list_pkvl_emplace);
cx_test_register(suite, test_list_kvl_insert_array);
cx_test_register(suite, test_list_pkvl_insert_array);
cx_test_register(suite, test_list_kvl_emplace_array);
cx_test_register(suite, test_list_pkvl_emplace_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_insert_unique_not_sorted);
cx_test_register(suite, test_list_pkvl_insert_unique_not_sorted);
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);
cx_test_register(suite, test_list_pkvl_remove_and_get);
cx_test_register(suite, test_list_kvl_remove_array);
cx_test_register(suite, test_list_pkvl_remove_array);
cx_test_register(suite, test_list_kvl_find_remove);
cx_test_register(suite, test_list_pkvl_find_remove);
cx_test_register(suite, test_list_kvl_find_remove_sorted);
cx_test_register(suite, test_list_pkvl_find_remove_sorted);
cx_test_register(suite, test_list_kvl_contains);
cx_test_register(suite, test_list_pkvl_contains);
cx_test_register(suite, test_list_kvl_clear);
cx_test_register(suite, test_list_pkvl_clear);
cx_test_register(suite, test_list_kvl_at);
cx_test_register(suite, test_list_pkvl_at);
cx_test_register(suite, test_list_kvl_set);
cx_test_register(suite, test_list_pkvl_set);
cx_test_register(suite, test_list_kvl_swap);
cx_test_register(suite, test_list_pkvl_swap);
cx_test_register(suite, test_list_kvl_find);
cx_test_register(suite, test_list_pkvl_find);
cx_test_register(suite, test_list_kvl_sort);
cx_test_register(suite, test_list_pkvl_sort);
cx_test_register(suite, test_list_kvl_reverse);
cx_test_register(suite, test_list_pkvl_reverse);
cx_test_register(suite, test_list_kvl_iterator);
cx_test_register(suite, test_list_pkvl_iterator);
cx_test_register(suite, test_list_kvl_insert_with_iterator);
cx_test_register(suite, test_list_pkvl_insert_with_iterator);
cx_test_register(suite, test_list_kvl_compare_ll);
cx_test_register(suite, test_list_kvl_compare_arl);
cx_test_register(suite, test_list_kvl_compare_pll);
cx_test_register(suite, test_list_kvl_compare_parl);
cx_test_register(suite, test_list_pkvl_compare_ll);
cx_test_register(suite, test_list_pkvl_compare_arl);
cx_test_register(suite, test_list_pkvl_compare_pll);
cx_test_register(suite, test_list_pkvl_compare_parl);
cx_test_register(suite, test_list_kvl_simple_destr);
cx_test_register(suite, test_list_pkvl_simple_destr);
cx_test_register(suite, test_list_kvl_advanced_destr);
cx_test_register(suite, test_list_pkvl_advanced_destr);
cx_test_register(suite, test_list_kvl_reserve_and_shrink);
cx_test_register(suite, test_list_pkvl_reserve_and_shrink);
cx_test_register(suite, test_list_kvl_clone_into_arl);
cx_test_register(suite, test_list_pkvl_clone_into_arl);
cx_test_register(suite, test_list_kvl_clone_into_ll);
cx_test_register(suite, test_list_pkvl_clone_into_ll);
cx_test_register(suite, test_list_kvl_clone_into_parl);
cx_test_register(suite, test_list_pkvl_clone_into_parl);
cx_test_register(suite, test_list_kvl_clone_into_pll);
cx_test_register(suite, test_list_pkvl_clone_into_pll);
cx_test_register(suite, test_list_kvl_clone_alloc_fail_into_arl);
cx_test_register(suite, test_list_pkvl_clone_alloc_fail_into_arl);
cx_test_register(suite, test_list_kvl_clone_alloc_fail_into_ll);
cx_test_register(suite, test_list_pkvl_clone_alloc_fail_into_ll);
cx_test_register(suite, test_list_kvl_clone_alloc_fail_into_parl);
cx_test_register(suite, test_list_pkvl_clone_alloc_fail_into_parl);
cx_test_register(suite, test_list_kvl_clone_alloc_fail_into_pll);
cx_test_register(suite, test_list_pkvl_clone_alloc_fail_into_pll);
return suite;
}
CxTestSuite *cx_test_suite_empty_list(
void) {
CxTestSuite *suite = cx_test_suite_new(
"empty list dummy");
cx_test_register(suite, test_empty_list_size);
cx_test_register(suite, test_empty_list_iterator);
cx_test_register(suite, test_null_list_iterator);
cx_test_register(suite, test_empty_list_noops);
cx_test_register(suite, test_empty_list_at);
cx_test_register(suite, test_empty_list_find);
cx_test_register(suite, test_empty_list_compare);
cx_test_register(suite, test_null_list_free);
return suite;
}
CxTestSuite *cx_test_suite_list_set_ops(
void) {
CxTestSuite *suite = cx_test_suite_new(
"list collection operations");
cx_test_register(suite, test_list_union_unsorted);
cx_test_register(suite, test_list_union_sorted);
cx_test_register(suite, test_list_union_unsorted_alloc_fail);
cx_test_register(suite, test_list_union_sorted_alloc_fail);
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);
cx_test_register(suite, test_list_intersection_unsorted);
cx_test_register(suite, test_list_intersection_sorted);
cx_test_register(suite, test_list_intersection_unsorted_alloc_fail);
cx_test_register(suite, test_list_intersection_sorted_alloc_fail);
cx_test_register(suite, test_list_simple_clones);
return suite;
}
CxTestSuite *cx_test_suite_list_corner_cases(
void) {
CxTestSuite *suite = cx_test_suite_new(
"list corner cases");
cx_test_register(suite, test_list_pointer_list_supports_null);
cx_test_register(suite, test_list_use_insert_unique_with_duplicates_in_source);
cx_test_register(suite, test_list_use_insert_unique_to_remove_duplicates);
return suite;
}