1 /*
2  * Copyright (c) 2019 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/sys/sflist.h>
9 
10 static sys_sflist_t test_list;
11 static sys_sflist_t append_list;
12 
13 struct container_node {
14 	sys_sfnode_t node;
15 	int unused;
16 };
17 
18 static struct container_node test_node_1;
19 static struct container_node test_node_2;
20 static struct container_node test_node_3;
21 static struct container_node test_node_4;
22 
verify_emptyness(sys_sflist_t * list)23 static inline bool verify_emptyness(sys_sflist_t *list)
24 {
25 	sys_sfnode_t *node;
26 	sys_sfnode_t *s_node;
27 	struct container_node *cnode;
28 	struct container_node *s_cnode;
29 	int count;
30 
31 	if (!sys_sflist_is_empty(list)) {
32 		return false;
33 	}
34 
35 	if (sys_sflist_peek_head(list)) {
36 		return false;
37 	}
38 
39 	if (sys_sflist_peek_tail(list)) {
40 		return false;
41 	}
42 
43 	if (sys_sflist_len(list) != 0) {
44 		return false;
45 	}
46 
47 	count = 0;
48 	SYS_SFLIST_FOR_EACH_NODE(list, node) {
49 		count++;
50 	}
51 
52 	if (count) {
53 		return false;
54 	}
55 
56 	SYS_SFLIST_FOR_EACH_NODE_SAFE(list, node, s_node) {
57 		count++;
58 	}
59 
60 	if (count) {
61 		return false;
62 	}
63 
64 	count = 0;
65 	SYS_SFLIST_FOR_EACH_CONTAINER(list, cnode, node) {
66 		count++;
67 	}
68 
69 	if (count) {
70 		return false;
71 	}
72 
73 	count = 0;
74 	SYS_SFLIST_FOR_EACH_CONTAINER_SAFE(list, cnode, s_cnode, node) {
75 		count++;
76 	}
77 
78 	if (count) {
79 		return false;
80 	}
81 
82 	return true;
83 }
84 
verify_content_amount(sys_sflist_t * list,int amount)85 static inline bool verify_content_amount(sys_sflist_t *list, int amount)
86 {
87 	sys_sfnode_t *node;
88 	sys_sfnode_t *s_node;
89 	struct container_node *cnode;
90 	struct container_node *s_cnode;
91 	int count;
92 
93 	if (sys_sflist_is_empty(list)) {
94 		return false;
95 	}
96 
97 	if (!sys_sflist_peek_head(list)) {
98 		return false;
99 	}
100 
101 	if (!sys_sflist_peek_tail(list)) {
102 		return false;
103 	}
104 
105 	if (sys_sflist_len(list) != amount) {
106 		return false;
107 	}
108 
109 	count = 0;
110 	SYS_SFLIST_FOR_EACH_NODE(list, node) {
111 		count++;
112 	}
113 
114 	if (count != amount) {
115 		return false;
116 	}
117 
118 	count = 0;
119 	SYS_SFLIST_FOR_EACH_NODE_SAFE(list, node, s_node) {
120 		count++;
121 	}
122 
123 	if (count != amount) {
124 		return false;
125 	}
126 
127 	count = 0;
128 	SYS_SFLIST_FOR_EACH_CONTAINER(list, cnode, node) {
129 		count++;
130 	}
131 
132 	if (count != amount) {
133 		return false;
134 	}
135 
136 	count = 0;
137 	SYS_SFLIST_FOR_EACH_CONTAINER_SAFE(list, cnode, s_cnode, node) {
138 		count++;
139 	}
140 
141 	if (count != amount) {
142 		return false;
143 	}
144 
145 	return true;
146 }
147 
verify_tail_head(sys_sflist_t * list,sys_sfnode_t * head,sys_sfnode_t * tail,bool same)148 static inline bool verify_tail_head(sys_sflist_t *list,
149 				    sys_sfnode_t *head,
150 				    sys_sfnode_t *tail,
151 				    bool same)
152 {
153 	if (sys_sflist_peek_head(list) != head) {
154 		return false;
155 	}
156 
157 	if (sys_sflist_peek_tail(list) != tail) {
158 		return false;
159 	}
160 
161 	if (same) {
162 		if (sys_sflist_peek_head(list) != sys_sflist_peek_tail(list)) {
163 			return false;
164 		}
165 	} else {
166 		if (sys_sflist_peek_head(list) == sys_sflist_peek_tail(list)) {
167 			return false;
168 		}
169 	}
170 
171 	return true;
172 }
173 /**
174  * @addtogroup kernel_common_tests
175  * @{
176  */
177 
178 /**
179  * @brief Test singly linked list functionalities
180  *
181  * @details Test list initialization, append item to the list,
182  * find and remove item, prepend, append, remove list
183  *
184  * @see sys_sflist_init(), sys_sflist_append(),
185  * sys_sflist_find_and_remove(), sys_sflist_prepend(),
186  * sys_sflist_remove(), sys_sflist_get(), sys_sflist_get_not_empty(),
187  * sys_sflist_append_list(), sys_sflist_merge_list()
188  */
ZTEST(dlist_api,test_sflist)189 ZTEST(dlist_api, test_sflist)
190 {
191 	sys_sflist_init(&test_list);
192 
193 	zassert_true((verify_emptyness(&test_list)),
194 		      "test_list should be empty");
195 
196 	/* Appending node 1 */
197 	sys_sflist_append(&test_list, &test_node_1.node);
198 	zassert_true((verify_content_amount(&test_list, 1)),
199 		     "test_list has wrong content");
200 
201 	zassert_true((verify_tail_head(&test_list, &test_node_1.node,
202 				       &test_node_1.node, true)),
203 		     "test_list head/tail are wrong");
204 
205 	/* Finding and removing node 1 */
206 	sys_sflist_find_and_remove(&test_list, &test_node_1.node);
207 	zassert_true((verify_emptyness(&test_list)),
208 		     "test_list should be empty");
209 
210 	/* Prepending node 1 */
211 	sys_sflist_prepend(&test_list, &test_node_1.node);
212 	zassert_true((verify_content_amount(&test_list, 1)),
213 		     "test_list has wrong content");
214 
215 	zassert_true((verify_tail_head(&test_list, &test_node_1.node,
216 				       &test_node_1.node, true)),
217 		     "test_list head/tail are wrong");
218 
219 	/* Removing node 1 */
220 	sys_sflist_remove(&test_list, NULL, &test_node_1.node);
221 	zassert_true((verify_emptyness(&test_list)),
222 		     "test_list should be empty");
223 
224 	/* Appending node 1 */
225 	sys_sflist_append(&test_list, &test_node_1.node);
226 	/* Prepending node 2 */
227 	sys_sflist_prepend(&test_list, &test_node_2.node);
228 
229 	zassert_true((verify_content_amount(&test_list, 2)),
230 		     "test_list has wrong content");
231 
232 	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
233 				       &test_node_1.node, false)),
234 		     "test_list head/tail are wrong");
235 
236 	/* Appending node 3 */
237 	sys_sflist_append(&test_list, &test_node_3.node);
238 
239 	zassert_true((verify_content_amount(&test_list, 3)),
240 		     "test_list has wrong content");
241 
242 	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
243 				       &test_node_3.node, false)),
244 		     "test_list head/tail are wrong");
245 
246 	zassert_true((sys_sflist_peek_next(&test_node_2.node) ==
247 		      &test_node_1.node),
248 		     "test_list node links are wrong");
249 
250 	/* Inserting node 4 after node 2, peek with nocheck variant */
251 	sys_sflist_insert(&test_list, &test_node_2.node, &test_node_4.node);
252 
253 	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
254 				       &test_node_3.node, false)),
255 		     "test_list head/tail are wrong");
256 
257 	zassert_true((sys_sflist_peek_next_no_check(&test_node_2.node) ==
258 		      &test_node_4.node),
259 		     "test_list node links are wrong");
260 
261 	/* Finding and removing node 1 */
262 	sys_sflist_find_and_remove(&test_list, &test_node_1.node);
263 	zassert_true((verify_content_amount(&test_list, 3)),
264 		     "test_list has wrong content");
265 
266 	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
267 				       &test_node_3.node, false)),
268 		     "test_list head/tail are wrong");
269 
270 	/* Removing node 3 */
271 	sys_sflist_remove(&test_list, &test_node_4.node, &test_node_3.node);
272 	zassert_true((verify_content_amount(&test_list, 2)),
273 		     "test_list has wrong content");
274 
275 	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
276 				       &test_node_4.node, false)),
277 		     "test_list head/tail are wrong");
278 
279 	/* Removing node 4 */
280 	sys_sflist_remove(&test_list, &test_node_2.node, &test_node_4.node);
281 	zassert_true((verify_content_amount(&test_list, 1)),
282 		     "test_list has wrong content");
283 
284 	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
285 				       &test_node_2.node, true)),
286 		     "test_list head/tail are wrong");
287 
288 	/* Removing node 2 */
289 	sys_sflist_remove(&test_list, NULL, &test_node_2.node);
290 	zassert_true((verify_emptyness(&test_list)),
291 		     "test_list should be empty");
292 
293 	/* test iterator from a node */
294 	struct data_node {
295 		sys_sfnode_t node;
296 		int data;
297 	} data_node[6] = {
298 		{ .data = 0 },
299 		{ .data = 1 },
300 		{ .data = 2 },
301 		{ .data = 3 },
302 		{ .data = 4 },
303 		{ .data = 5 },
304 	};
305 	sys_sfnode_t *node = NULL;
306 	int ii;
307 
308 	sys_sflist_init(&test_list);
309 
310 	for (ii = 0; ii < 6; ii++) {
311 		sys_sflist_append(&test_list, &data_node[ii].node);
312 	}
313 
314 	ii = 0;
315 	SYS_SFLIST_ITERATE_FROM_NODE(&test_list, node) {
316 		ii++;
317 		if (((struct data_node *)node)->data == 2) {
318 			break;
319 		}
320 	}
321 	zassert_equal(ii, 3, "");
322 
323 	ii = 0;
324 	SYS_SFLIST_ITERATE_FROM_NODE(&test_list, node) {
325 		ii++;
326 		if (((struct data_node *)node)->data == 3) {
327 			break;
328 		}
329 	}
330 	zassert_equal(ii, 1, "");
331 
332 	ii = 0;
333 	SYS_SFLIST_ITERATE_FROM_NODE(&test_list, node) {
334 		ii++;
335 	}
336 	zassert_equal(ii, 2, "");
337 
338 	/* test sys_sflist_get_not_empty() and sys_sflist_get() APIs */
339 	for (ii = 0; ii < 6; ii++) {
340 		node = sys_sflist_get_not_empty(&test_list);
341 		zassert_equal(((struct data_node *)node)->data, ii, "");
342 	}
343 	for (ii = 0; ii < 6; ii++) {
344 		/* regenerate test_list since we just emptied it */
345 		sys_sflist_append(&test_list, &data_node[ii].node);
346 	}
347 	for (ii = 0; ii < 6; ii++) {
348 		node = sys_sflist_get(&test_list);
349 		zassert_equal(((struct data_node *)node)->data, ii, "");
350 	}
351 	node = sys_sflist_get(&test_list);
352 	zassert_equal(node, NULL, "");
353 
354 	/* test sys_sflist_append_list() */
355 	sys_sflist_init(&append_list);
356 	struct data_node data_node_append[6] = {
357 		{ .data = 6 },
358 		{ .data = 7 },
359 		{ .data = 8 },
360 		{ .data = 9 },
361 		{ .data = 10 },
362 		{ .data = 11 },
363 	};
364 	for (ii = 0; ii < 6; ii++) {
365 		/* regenerate test_list, which we just emptied */
366 		sys_sflist_append(&test_list, &data_node[ii].node);
367 		/* Build append_list so that the node pointers are correct */
368 		sys_sflist_append(&append_list, &data_node_append[ii].node);
369 	}
370 	sys_sflist_append_list(&test_list, &data_node_append[0].node,
371 			      &data_node_append[5].node);
372 	for (ii = 0; ii < 12; ii++) {
373 		node = sys_sflist_get(&test_list);
374 		zassert_equal(((struct data_node *)node)->data, ii,
375 			      "expected %d got %d", ii,
376 			      ((struct data_node *)node)->data);
377 	}
378 
379 	/* test sys_sflist_merge_sflist */
380 	sys_sflist_init(&test_list);
381 	sys_sflist_init(&append_list);
382 	for (ii = 0; ii < 6; ii++) {
383 		/* regenerate both lists */
384 		sys_sflist_append(&test_list, &data_node[ii].node);
385 		sys_sflist_append(&append_list, &data_node_append[ii].node);
386 	}
387 	sys_sflist_merge_sflist(&test_list, &append_list);
388 	for (ii = 0; ii < 12; ii++) {
389 		node = sys_sflist_get(&test_list);
390 		zassert_equal(((struct data_node *)node)->data, ii,
391 			      "expected %d got %d", ii,
392 			      ((struct data_node *)node)->data);
393 	}
394 	zassert_true(sys_sflist_is_empty(&append_list),
395 		     "merged list is not empty");
396 
397 	/* tests for sys_sfnode_flags_get(), sys_sfnode_flags_set()
398 	 * sys_sfnode_init()
399 	 */
400 	sys_sflist_init(&test_list);
401 	/* Only iterating 0..3 due to limited range of flag values */
402 	for (ii = 0; ii < 4; ii++) {
403 		sys_sfnode_init(&data_node[ii].node, ii);
404 		sys_sflist_append(&test_list, &data_node[ii].node);
405 	}
406 	for (ii = 0; ii < 4; ii++) {
407 		node = sys_sflist_get(&test_list);
408 		zassert_equal(sys_sfnode_flags_get(node), ii,
409 			      "wrong flags value");
410 		/* Place the nodes back on the list with the flags set
411 		 * in reverse order for the next test
412 		 */
413 		sys_sfnode_flags_set(node, 3 - ii);
414 		sys_sflist_append(&test_list, node);
415 	}
416 	for (ii = 3; ii >= 0; ii--) {
417 		node = sys_sflist_get(&test_list);
418 		zassert_equal(sys_sfnode_flags_get(node), ii,
419 			      "wrong flags value");
420 	}
421 }
422 
423 /**
424  * @}
425  */
426