2 * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
28 /* Forcibly enable assertions for list_check() */
34 #include <ipxe/list.h>
35 #include <ipxe/test.h>
37 /** A list test structure */
40 struct list_head list;
45 /** List test elements */
46 static struct list_test list_tests[] = {
60 static LIST_HEAD ( test_list );
63 * Check list contents are as expected
66 * @v expected Expected contents
67 * @v ok List contents are as expected
69 static int list_check_contents ( struct list_head *list,
70 const char *expected ) {
71 struct list_test *entry;
72 size_t num_entries = 0;
74 /* Determine size of list */
75 list_for_each_entry ( entry, list, list )
79 char found[ num_entries + 1 ];
80 char found_rev[ num_entries + 1 ];
83 /* Build up list content string */
85 list_for_each_entry ( entry, list, list )
86 *(tmp++) = entry->label;
89 /* Sanity check reversed list */
90 tmp = &found_rev[ sizeof ( found_rev ) - 1 ];
92 list_for_each_entry_reverse ( entry, list, list )
93 *(--tmp) = entry->label;
94 if ( strcmp ( found, found_rev ) != 0 ) {
95 printf ( "FAILURE: list reversal mismatch (forward "
96 "\"%s\", reverse \"%s\")\n",
101 /* Compare against expected content */
102 if ( strcmp ( found, expected ) == 0 ) {
105 printf ( "FAILURE: expected \"%s\", got \"%s\"\n",
113 * Report list test result
116 * @v expected Expected contents
118 #define list_contents_ok( list, expected ) do { \
119 ok ( list_check_contents ( (list), (expected) ) ); \
123 * Report list iteration test result
125 * @v macro Iterator macro
126 * @v expected Expected contents
128 * @v ... Arguments to iterator macro
130 #define list_iterate_ok( macro, expected, pos, ... ) do { \
131 const char *check = expected; \
132 macro ( pos, __VA_ARGS__ ) { \
133 struct list_test *entry = \
134 list_entry ( pos, struct list_test, \
136 ok ( entry->label == *(check++) ); \
138 ok ( *check == '\0' ); \
142 * Report list entry iteration test result
144 * @v macro Iterator macro
145 * @v expected Expected contents
147 * @v ... Arguments to iterator macro
149 #define list_iterate_entry_ok( macro, expected, pos, ... ) do { \
150 const char *check = expected; \
151 macro ( pos, __VA_ARGS__ ) { \
152 ok ( (pos)->label == *(check++) ); \
154 ok ( *check == '\0' ); \
158 * Perform list self-test
161 static void list_test_exec ( void ) {
162 struct list_head *list = &test_list;
163 struct list_head target_list;
164 struct list_head *target = &target_list;
165 struct list_head *raw_pos;
166 struct list_test *pos;
167 struct list_test *tmp;
169 /* Test initialiser and list_empty() */
170 ok ( list_empty ( list ) );
171 list_contents_ok ( list, "" );
173 /* Test list_add(), list_add_tail() and list_del() */
174 INIT_LIST_HEAD ( list );
175 list_contents_ok ( list, "" );
176 list_add ( &list_tests[4].list, list ); /* prepend */
177 list_contents_ok ( list, "4" );
178 list_add ( &list_tests[2].list, list ); /* prepend */
179 list_contents_ok ( list, "24" );
180 list_add_tail ( &list_tests[7].list, list ); /* append */
181 list_contents_ok ( list, "247" );
182 list_add ( &list_tests[1].list, &list_tests[4].list ); /* after */
183 list_contents_ok ( list, "2417" );
184 list_add_tail ( &list_tests[8].list, &list_tests[7].list ); /* before */
185 list_contents_ok ( list, "24187" );
186 list_del ( &list_tests[4].list ); /* delete middle */
187 list_contents_ok ( list, "2187" );
188 list_del ( &list_tests[2].list ); /* delete first */
189 list_contents_ok ( list, "187" );
190 list_del ( &list_tests[7].list ); /* delete last */
191 list_contents_ok ( list, "18" );
192 list_del ( &list_tests[1].list ); /* delete all */
193 list_del ( &list_tests[8].list ); /* delete all */
194 list_contents_ok ( list, "" );
195 ok ( list_empty ( list ) );
197 /* Test list_is_singular() */
198 INIT_LIST_HEAD ( list );
199 ok ( ! list_is_singular ( list ) );
200 list_add ( &list_tests[1].list, list );
201 ok ( list_is_singular ( list ) );
202 list_add ( &list_tests[3].list, list );
203 ok ( ! list_is_singular ( list ) );
204 list_del ( &list_tests[1].list );
205 ok ( list_is_singular ( list ) );
207 /* Test list_is_last() */
208 INIT_LIST_HEAD ( list );
209 list_add_tail ( &list_tests[6].list, list );
210 ok ( list_is_last ( &list_tests[6].list, list ) );
211 list_add_tail ( &list_tests[4].list, list );
212 ok ( list_is_last ( &list_tests[4].list, list ) );
213 ok ( ! list_is_last ( &list_tests[6].list, list ) );
215 /* Test list_cut_position() - empty list */
216 INIT_LIST_HEAD ( list );
217 INIT_LIST_HEAD ( target );
218 list_cut_position ( target, list, list );
219 list_contents_ok ( list, "" );
220 list_contents_ok ( target, "" );
222 /* Test list_cut_position() - singular list, move nothing */
223 INIT_LIST_HEAD ( list );
224 INIT_LIST_HEAD ( target );
225 list_add_tail ( &list_tests[4].list, list );
226 list_cut_position ( target, list, list );
227 list_contents_ok ( list, "4" );
228 list_contents_ok ( target, "" );
230 /* Test list_cut_position() - singular list, move singular entry */
231 INIT_LIST_HEAD ( list );
232 INIT_LIST_HEAD ( target );
233 list_add_tail ( &list_tests[9].list, list );
234 list_cut_position ( target, list, &list_tests[9].list );
235 list_contents_ok ( list, "" );
236 list_contents_ok ( target, "9" );
238 /* Test list_cut_position() - multi-entry list, move nothing */
239 INIT_LIST_HEAD ( list );
240 list_add_tail ( &list_tests[3].list, list );
241 list_add_tail ( &list_tests[2].list, list );
242 list_add_tail ( &list_tests[7].list, list );
243 INIT_LIST_HEAD ( target );
244 list_cut_position ( target, list, list );
245 list_contents_ok ( list, "327" );
246 list_contents_ok ( target, "" );
248 /* Test list_cut_position() - multi-entry list, move some */
249 INIT_LIST_HEAD ( list );
250 INIT_LIST_HEAD ( target );
251 list_add_tail ( &list_tests[8].list, list );
252 list_add_tail ( &list_tests[0].list, list );
253 list_add_tail ( &list_tests[9].list, list );
254 list_add_tail ( &list_tests[3].list, list );
255 list_add_tail ( &list_tests[2].list, list );
256 list_cut_position ( target, list, &list_tests[0].list );
257 list_contents_ok ( list, "932" );
258 list_contents_ok ( target, "80" );
260 /* Test list_cut_position() - multi-entry list, move everything */
261 INIT_LIST_HEAD ( list );
262 INIT_LIST_HEAD ( target );
263 list_add_tail ( &list_tests[3].list, list );
264 list_add_tail ( &list_tests[5].list, list );
265 list_add_tail ( &list_tests[4].list, list );
266 list_add_tail ( &list_tests[7].list, list );
267 list_add_tail ( &list_tests[1].list, list );
268 list_cut_position ( target, list, &list_tests[1].list );
269 list_contents_ok ( list, "" );
270 list_contents_ok ( target, "35471" );
272 /* Test list_splice() - empty list */
273 INIT_LIST_HEAD ( list );
274 INIT_LIST_HEAD ( target );
275 list_splice ( list, target );
276 list_contents_ok ( list, "" );
277 list_contents_ok ( target, "" );
279 /* Test list_splice() - both lists empty */
280 INIT_LIST_HEAD ( list );
281 INIT_LIST_HEAD ( target );
282 list_splice ( list, target );
283 list_contents_ok ( target, "" );
285 /* Test list_splice() - source list empty */
286 INIT_LIST_HEAD ( list );
287 INIT_LIST_HEAD ( target );
288 list_add_tail ( &list_tests[1].list, target );
289 list_add_tail ( &list_tests[3].list, target );
290 list_splice ( list, &list_tests[1].list );
291 list_contents_ok ( target, "13" );
293 /* Test list_splice() - destination list empty */
294 INIT_LIST_HEAD ( list );
295 INIT_LIST_HEAD ( target );
296 list_add_tail ( &list_tests[6].list, list );
297 list_add_tail ( &list_tests[5].list, list );
298 list_add_tail ( &list_tests[2].list, list );
299 list_splice ( list, target );
300 list_contents_ok ( target, "652" );
302 /* Test list_splice() - both lists non-empty */
303 INIT_LIST_HEAD ( list );
304 INIT_LIST_HEAD ( target );
305 list_add_tail ( &list_tests[8].list, list );
306 list_add_tail ( &list_tests[4].list, list );
307 list_add_tail ( &list_tests[5].list, list );
308 list_add_tail ( &list_tests[1].list, target );
309 list_add_tail ( &list_tests[9].list, target );
310 list_splice ( list, &list_tests[1].list );
311 list_contents_ok ( target, "18459" );
313 /* Test list_splice_tail() - both lists empty */
314 INIT_LIST_HEAD ( list );
315 INIT_LIST_HEAD ( target );
316 list_splice_tail ( list, target );
317 list_contents_ok ( target, "" );
319 /* Test list_splice_tail() - source list empty */
320 INIT_LIST_HEAD ( list );
321 INIT_LIST_HEAD ( target );
322 list_add_tail ( &list_tests[5].list, target );
323 list_splice_tail ( list, &list_tests[5].list );
324 list_contents_ok ( target, "5" );
326 /* Test list_splice_tail() - destination list empty */
327 INIT_LIST_HEAD ( list );
328 INIT_LIST_HEAD ( target );
329 list_add_tail ( &list_tests[2].list, list );
330 list_add_tail ( &list_tests[1].list, list );
331 list_add_tail ( &list_tests[0].list, list );
332 list_splice_tail ( list, target );
333 list_contents_ok ( target, "210" );
335 /* Test list_splice_tail() - both lists non-empty */
336 INIT_LIST_HEAD ( list );
337 INIT_LIST_HEAD ( target );
338 list_add_tail ( &list_tests[9].list, list );
339 list_add_tail ( &list_tests[5].list, list );
340 list_add_tail ( &list_tests[7].list, list );
341 list_add_tail ( &list_tests[2].list, target );
342 list_add_tail ( &list_tests[4].list, target );
343 list_splice_tail ( list, &list_tests[2].list );
344 list_contents_ok ( target, "95724" );
346 /* Test list_splice_init() */
347 INIT_LIST_HEAD ( list );
348 INIT_LIST_HEAD ( target );
349 list_add_tail ( &list_tests[4].list, list );
350 list_add_tail ( &list_tests[1].list, target );
351 list_splice_init ( list, target );
352 ok ( list_empty ( list ) );
353 list_contents_ok ( list, "" );
354 list_contents_ok ( target, "41" );
356 /* Test list_splice_tail_init() */
357 INIT_LIST_HEAD ( list );
358 INIT_LIST_HEAD ( target );
359 list_add_tail ( &list_tests[3].list, list );
360 list_add_tail ( &list_tests[2].list, list );
361 list_add_tail ( &list_tests[5].list, target );
362 list_splice_tail_init ( list, &list_tests[5].list );
363 ok ( list_empty ( list ) );
364 list_contents_ok ( list, "" );
365 list_contents_ok ( target, "325" );
367 /* Test list_entry() */
368 INIT_LIST_HEAD ( &list_tests[3].list ); // for list_check()
369 ok ( list_entry ( &list_tests[3].list, struct list_test, list )
372 /* Test list_first_entry() and list_last_entry() */
373 INIT_LIST_HEAD ( list );
374 list_add_tail ( &list_tests[9].list, list );
375 list_add_tail ( &list_tests[5].list, list );
376 list_add_tail ( &list_tests[6].list, list );
377 ok ( list_first_entry ( list, struct list_test, list )
379 ok ( list_last_entry ( list, struct list_test, list )
381 list_del ( &list_tests[9].list );
382 ok ( list_first_entry ( list, struct list_test, list )
384 ok ( list_last_entry ( list, struct list_test, list )
386 list_del ( &list_tests[6].list );
387 ok ( list_first_entry ( list, struct list_test, list )
389 ok ( list_last_entry ( list, struct list_test, list )
391 list_del ( &list_tests[5].list );
392 ok ( list_first_entry ( list, struct list_test, list ) == NULL );
393 ok ( list_last_entry ( list, struct list_test, list ) == NULL );
395 /* Test list_for_each() */
396 INIT_LIST_HEAD ( list );
397 list_add_tail ( &list_tests[6].list, list );
398 list_add_tail ( &list_tests[7].list, list );
399 list_add_tail ( &list_tests[3].list, list );
400 list_iterate_ok ( list_for_each, "673", raw_pos, list );
402 /* Test list_for_each_entry() and list_for_each_entry_reverse() */
403 INIT_LIST_HEAD ( list );
404 list_add_tail ( &list_tests[3].list, list );
405 list_add_tail ( &list_tests[2].list, list );
406 list_add_tail ( &list_tests[6].list, list );
407 list_add_tail ( &list_tests[9].list, list );
408 list_iterate_entry_ok ( list_for_each_entry, "3269",
410 list_iterate_entry_ok ( list_for_each_entry_reverse, "9623",
413 /* Test list_for_each_entry_safe() */
414 INIT_LIST_HEAD ( list );
415 list_add_tail ( &list_tests[2].list, list );
416 list_add_tail ( &list_tests[4].list, list );
417 list_add_tail ( &list_tests[1].list, list );
419 char *expected = "241";
420 list_for_each_entry_safe ( pos, tmp, list, list ) {
421 list_contents_ok ( list, expected );
422 list_del ( &pos->list );
424 list_contents_ok ( list, expected );
427 ok ( list_empty ( list ) );
429 /* Test list_for_each_entry_continue() and
430 * list_for_each_entry_continue_reverse()
432 INIT_LIST_HEAD ( list );
433 list_add_tail ( &list_tests[4].list, list );
434 list_add_tail ( &list_tests[7].list, list );
435 list_add_tail ( &list_tests[2].list, list );
436 list_add_tail ( &list_tests[9].list, list );
437 list_add_tail ( &list_tests[3].list, list );
438 pos = &list_tests[7];
439 list_iterate_entry_ok ( list_for_each_entry_continue, "293",
441 ok ( pos == list_entry ( list, struct list_test, list ) );
442 list_iterate_entry_ok ( list_for_each_entry_continue, "47293",
444 pos = &list_tests[3];
445 list_iterate_entry_ok ( list_for_each_entry_continue, "",
447 pos = &list_tests[2];
448 list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "74",
450 ok ( pos == list_entry ( list, struct list_test, list ) );
451 list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "39274",
453 pos = &list_tests[4];
454 list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "",
457 /* Test list_contains() and list_contains_entry() */
458 INIT_LIST_HEAD ( list );
459 INIT_LIST_HEAD ( &list_tests[3].list );
460 list_add ( &list_tests[8].list, list );
461 list_add ( &list_tests[5].list, list );
462 ok ( list_contains ( &list_tests[8].list, list ) );
463 ok ( list_contains_entry ( &list_tests[8], list, list ) );
464 ok ( list_contains ( &list_tests[5].list, list ) );
465 ok ( list_contains_entry ( &list_tests[5], list, list ) );
466 ok ( ! list_contains ( &list_tests[3].list, list ) );
467 ok ( ! list_contains_entry ( &list_tests[3], list, list ) );
469 /* Test list_check_contains_entry() */
470 INIT_LIST_HEAD ( list );
471 list_add ( &list_tests[4].list, list );
472 list_add ( &list_tests[0].list, list );
473 list_add ( &list_tests[3].list, list );
474 list_check_contains_entry ( &list_tests[4], list, list );
475 list_check_contains_entry ( &list_tests[0], list, list );
476 list_check_contains_entry ( &list_tests[3], list, list );
479 /** List self-test */
480 struct self_test list_test __self_test = {
482 .exec = list_test_exec,