ohmu
·
2026-10-15
1#include "common/FFlist.h"
2#include "common/textModifier.h"
3
4#include <string.h>
5#include <stdarg.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <stdnoreturn.h>
9
10noreturn static void testFailed(const FFlist* list, const char* expression, int lineNo) {
11 fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stderr);
12 fprintf(stderr, "[%d] %s, list:", lineNo, expression);
13 for (uint32_t i = 0; i < list->length; ++i) {
14 fprintf(stderr, "%u ", *FF_LIST_GET(uint32_t, *list, i));
15 }
16 fputc('\n', stderr);
17 fputs(FASTFETCH_TEXT_MODIFIER_RESET, stderr);
18 fputc('\n', stderr);
19 exit(1);
20}
21
22static bool numEqualsAdapter(const uint32_t* first, const uint32_t* second) {
23 return *first == *second;
24}
25
26#define VERIFY(expression) \
27 if (!(expression)) testFailed(&list, #expression, __LINE__)
28
29int main(void) {
30 FFlist list;
31 uint32_t n = 0;
32
33 // initA
34
35 ffListInit(&list);
36
37 VERIFY(list.capacity == 0);
38 VERIFY(list.length == 0);
39
40 // forEach
41 FF_LIST_FOR_EACH (uint32_t, item, list) {
42 VERIFY(false);
43 }
44
45 // shift
46 VERIFY(!FF_LIST_SHIFT(list, &n));
47 VERIFY(list.length == 0);
48
49 // pop
50 VERIFY(!FF_LIST_POP(list, &n));
51 VERIFY(list.length == 0);
52
53 // add
54 for (uint32_t i = 1; i <= FF_LIST_DEFAULT_ALLOC + 1; ++i) {
55 *FF_LIST_ADD(uint32_t, list) = i;
56
57 VERIFY(list.length == i);
58
59 if (i <= FF_LIST_DEFAULT_ALLOC) {
60 VERIFY(list.capacity == FF_LIST_DEFAULT_ALLOC);
61 } else {
62 VERIFY(list.capacity == FF_LIST_DEFAULT_ALLOC * 2);
63 }
64
65 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 1);
66 VERIFY(*FF_LIST_GET(uint32_t, list, i - 1) == i);
67 }
68 VERIFY(list.length == FF_LIST_DEFAULT_ALLOC + 1);
69
70 uint32_t sum = 0;
71 // forEach
72 FF_LIST_FOR_EACH (uint32_t, item, list) {
73 sum += *item;
74 }
75 VERIFY(sum == (1 + FF_LIST_DEFAULT_ALLOC + 1) * (FF_LIST_DEFAULT_ALLOC + 1) / 2);
76
77 // ffListFirstIndexComp
78 n = 10;
79 VERIFY(ffListFirstIndexComp(&list, sizeof(n), &n, (void*) numEqualsAdapter) == 9);
80 n = 999;
81 VERIFY(ffListFirstIndexComp(&list, sizeof(n), &n, (void*) numEqualsAdapter) == list.length);
82
83 // ffListContains
84 n = 10;
85 VERIFY(FF_LIST_CONTAINS(list, &n, numEqualsAdapter));
86 n = 999;
87 VERIFY(!FF_LIST_CONTAINS(list, &n, numEqualsAdapter));
88
89 // shift
90 VERIFY(FF_LIST_SHIFT(list, &n));
91 VERIFY(n == 1);
92 VERIFY(list.length == FF_LIST_DEFAULT_ALLOC);
93 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 2);
94 VERIFY(*FF_LIST_GET(uint32_t, list, list.length - 1) == FF_LIST_DEFAULT_ALLOC + 1);
95
96 // pop
97 VERIFY(FF_LIST_POP(list, &n));
98 VERIFY(n == FF_LIST_DEFAULT_ALLOC + 1);
99 VERIFY(list.length == FF_LIST_DEFAULT_ALLOC - 1);
100 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 2);
101 VERIFY(*FF_LIST_GET(uint32_t, list, list.length - 1) == FF_LIST_DEFAULT_ALLOC);
102
103 // insertAt
104 ffListClear(&list);
105 for (uint32_t i = 1; i <= 5; ++i) {
106 *FF_LIST_ADD(uint32_t, list) = i;
107 }
108 // list = [1,2,3,4,5]
109
110 {
111 uint32_t v = 0;
112 FF_LIST_INSERT_AT(uint32_t, list, 0, &v); // insert at head
113 }
114 VERIFY(list.length == 6);
115 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 0);
116 VERIFY(*FF_LIST_GET(uint32_t, list, 1) == 1);
117 VERIFY(*FF_LIST_GET(uint32_t, list, 5) == 5);
118 // list = [0,1,2,3,4,5]
119
120 {
121 uint32_t v = 99;
122 FF_LIST_INSERT_AT(uint32_t, list, 3, &v); // insert in the middle
123 }
124 VERIFY(list.length == 7);
125 VERIFY(*FF_LIST_GET(uint32_t, list, 2) == 2);
126 VERIFY(*FF_LIST_GET(uint32_t, list, 3) == 99);
127 VERIFY(*FF_LIST_GET(uint32_t, list, 4) == 3);
128 VERIFY(*FF_LIST_GET(uint32_t, list, 6) == 5);
129 // list = [0,1,2,99,3,4,5]
130
131 {
132 uint32_t v = 6;
133 FF_LIST_INSERT_AT(uint32_t, list, list.length, &v); // insert at tail
134 }
135 VERIFY(list.length == 8);
136 VERIFY(*FF_LIST_GET(uint32_t, list, 3) == 99);
137 VERIFY(*FF_LIST_GET(uint32_t, list, 7) == 6);
138 // list = [0,1,2,99,3,4,5,6]
139
140 ffListClear(&list);
141 {
142 uint32_t v = 42;
143 FF_LIST_INSERT_AT(uint32_t, list, 0, &v); // insert into empty list
144 }
145 VERIFY(list.length == 1);
146 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 42);
147
148 // removeAt
149 FF_LIST_REMOVE_AT(uint32_t, list, 0); // remove the only element
150 VERIFY(list.length == 0);
151
152 for (uint32_t i = 1; i <= 5; ++i) {
153 *FF_LIST_ADD(uint32_t, list) = i;
154 }
155 // list = [1,2,3,4,5]
156
157 FF_LIST_REMOVE_AT(uint32_t, list, 0); // remove head
158 VERIFY(list.length == 4);
159 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 2);
160 VERIFY(*FF_LIST_GET(uint32_t, list, list.length - 1) == 5);
161 // list = [2,3,4,5]
162
163 FF_LIST_REMOVE_AT(uint32_t, list, 1); // remove in the middle
164 VERIFY(list.length == 3);
165 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 2);
166 VERIFY(*FF_LIST_GET(uint32_t, list, 1) == 4);
167 VERIFY(*FF_LIST_GET(uint32_t, list, 2) == 5);
168 // list = [2,4,5]
169
170 FF_LIST_REMOVE_AT(uint32_t, list, list.length - 1); // remove tail
171 VERIFY(list.length == 2);
172 VERIFY(*FF_LIST_GET(uint32_t, list, 0) == 2);
173 VERIFY(*FF_LIST_GET(uint32_t, list, 1) == 4);
174 // list = [2,4]
175
176 // Destroy
177 ffListDestroy(&list);
178
179 VERIFY(list.capacity == 0);
180 VERIFY(list.length == 0);
181
182 {
183 FF_LIST_AUTO_DESTROY test = ffListCreate();
184 VERIFY(test.capacity == 0);
185 VERIFY(test.length == 0);
186 }
187
188 // Success
189 puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
190}