You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

list_test.c 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  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.
  8. *
  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.
  13. *
  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
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. /** @file
  21. *
  22. * List function tests
  23. *
  24. */
  25. /* Forcibly enable assertions for list_check() */
  26. #undef NDEBUG
  27. #include <assert.h>
  28. #include <string.h>
  29. #include <stdio.h>
  30. #include <ipxe/list.h>
  31. #include <ipxe/test.h>
  32. /** A list test structure */
  33. struct list_test {
  34. /** List element */
  35. struct list_head list;
  36. /** Label */
  37. char label;
  38. };
  39. /** List test elements */
  40. static struct list_test list_tests[] = {
  41. { .label = '0' },
  42. { .label = '1' },
  43. { .label = '2' },
  44. { .label = '3' },
  45. { .label = '4' },
  46. { .label = '5' },
  47. { .label = '6' },
  48. { .label = '7' },
  49. { .label = '8' },
  50. { .label = '9' },
  51. };
  52. /** Test list */
  53. static LIST_HEAD ( test_list );
  54. /**
  55. * Check list contents are as expected
  56. *
  57. * @v list Test list
  58. * @v expected Expected contents
  59. * @v ok List contents are as expected
  60. */
  61. static int list_check_contents ( struct list_head *list,
  62. const char *expected ) {
  63. struct list_test *entry;
  64. size_t num_entries = 0;
  65. /* Determine size of list */
  66. list_for_each_entry ( entry, list, list )
  67. num_entries++;
  68. {
  69. char found[ num_entries + 1 ];
  70. char found_rev[ num_entries + 1 ];
  71. char *tmp;
  72. /* Build up list content string */
  73. tmp = found;
  74. list_for_each_entry ( entry, list, list )
  75. *(tmp++) = entry->label;
  76. *tmp = '\0';
  77. /* Sanity check reversed list */
  78. tmp = &found_rev[ sizeof ( found_rev ) - 1 ];
  79. *tmp = '\0';
  80. list_for_each_entry_reverse ( entry, list, list )
  81. *(--tmp) = entry->label;
  82. if ( strcmp ( found, found_rev ) != 0 ) {
  83. printf ( "FAILURE: list reversal mismatch (forward "
  84. "\"%s\", reverse \"%s\")\n",
  85. found, found_rev );
  86. return 0;
  87. }
  88. /* Compare against expected content */
  89. if ( strcmp ( found, expected ) == 0 ) {
  90. return 1;
  91. } else {
  92. printf ( "FAILURE: expected \"%s\", got \"%s\"\n",
  93. expected, found );
  94. return 0;
  95. }
  96. }
  97. }
  98. /**
  99. * Report list test result
  100. *
  101. * @v list Test list
  102. * @v expected Expected contents
  103. */
  104. #define list_contents_ok( list, expected ) do { \
  105. ok ( list_check_contents ( (list), (expected) ) ); \
  106. } while ( 0 )
  107. /**
  108. * Report list iteration test result
  109. *
  110. * @v macro Iterator macro
  111. * @v expected Expected contents
  112. * @v pos Iterator
  113. * @v ... Arguments to iterator macro
  114. */
  115. #define list_iterate_ok( macro, expected, pos, ... ) do { \
  116. const char *check = expected; \
  117. macro ( pos, __VA_ARGS__ ) { \
  118. struct list_test *entry = \
  119. list_entry ( pos, struct list_test, \
  120. list ); \
  121. ok ( entry->label == *(check++) ); \
  122. } \
  123. ok ( *check == '\0' ); \
  124. } while ( 0 )
  125. /**
  126. * Report list entry iteration test result
  127. *
  128. * @v macro Iterator macro
  129. * @v expected Expected contents
  130. * @v pos Iterator
  131. * @v ... Arguments to iterator macro
  132. */
  133. #define list_iterate_entry_ok( macro, expected, pos, ... ) do { \
  134. const char *check = expected; \
  135. macro ( pos, __VA_ARGS__ ) { \
  136. ok ( (pos)->label == *(check++) ); \
  137. } \
  138. ok ( *check == '\0' ); \
  139. } while ( 0 )
  140. /**
  141. * Perform list self-test
  142. *
  143. */
  144. static void list_test_exec ( void ) {
  145. struct list_head *list = &test_list;
  146. struct list_head target_list;
  147. struct list_head *target = &target_list;
  148. struct list_head *raw_pos;
  149. struct list_test *pos;
  150. struct list_test *tmp;
  151. /* Test initialiser and list_empty() */
  152. ok ( list_empty ( list ) );
  153. list_contents_ok ( list, "" );
  154. /* Test list_add(), list_add_tail() and list_del() */
  155. INIT_LIST_HEAD ( list );
  156. list_contents_ok ( list, "" );
  157. list_add ( &list_tests[4].list, list ); /* prepend */
  158. list_contents_ok ( list, "4" );
  159. list_add ( &list_tests[2].list, list ); /* prepend */
  160. list_contents_ok ( list, "24" );
  161. list_add_tail ( &list_tests[7].list, list ); /* append */
  162. list_contents_ok ( list, "247" );
  163. list_add ( &list_tests[1].list, &list_tests[4].list ); /* after */
  164. list_contents_ok ( list, "2417" );
  165. list_add_tail ( &list_tests[8].list, &list_tests[7].list ); /* before */
  166. list_contents_ok ( list, "24187" );
  167. list_del ( &list_tests[4].list ); /* delete middle */
  168. list_contents_ok ( list, "2187" );
  169. list_del ( &list_tests[2].list ); /* delete first */
  170. list_contents_ok ( list, "187" );
  171. list_del ( &list_tests[7].list ); /* delete last */
  172. list_contents_ok ( list, "18" );
  173. list_del ( &list_tests[1].list ); /* delete all */
  174. list_del ( &list_tests[8].list ); /* delete all */
  175. list_contents_ok ( list, "" );
  176. ok ( list_empty ( list ) );
  177. /* Test list_is_singular() */
  178. INIT_LIST_HEAD ( list );
  179. ok ( ! list_is_singular ( list ) );
  180. list_add ( &list_tests[1].list, list );
  181. ok ( list_is_singular ( list ) );
  182. list_add ( &list_tests[3].list, list );
  183. ok ( ! list_is_singular ( list ) );
  184. list_del ( &list_tests[1].list );
  185. ok ( list_is_singular ( list ) );
  186. /* Test list_is_last() */
  187. INIT_LIST_HEAD ( list );
  188. list_add_tail ( &list_tests[6].list, list );
  189. ok ( list_is_last ( &list_tests[6].list, list ) );
  190. list_add_tail ( &list_tests[4].list, list );
  191. ok ( list_is_last ( &list_tests[4].list, list ) );
  192. ok ( ! list_is_last ( &list_tests[6].list, list ) );
  193. /* Test list_cut_position() - empty list */
  194. INIT_LIST_HEAD ( list );
  195. INIT_LIST_HEAD ( target );
  196. list_cut_position ( target, list, list );
  197. list_contents_ok ( list, "" );
  198. list_contents_ok ( target, "" );
  199. /* Test list_cut_position() - singular list, move nothing */
  200. INIT_LIST_HEAD ( list );
  201. INIT_LIST_HEAD ( target );
  202. list_add_tail ( &list_tests[4].list, list );
  203. list_cut_position ( target, list, list );
  204. list_contents_ok ( list, "4" );
  205. list_contents_ok ( target, "" );
  206. /* Test list_cut_position() - singular list, move singular entry */
  207. INIT_LIST_HEAD ( list );
  208. INIT_LIST_HEAD ( target );
  209. list_add_tail ( &list_tests[9].list, list );
  210. list_cut_position ( target, list, &list_tests[9].list );
  211. list_contents_ok ( list, "" );
  212. list_contents_ok ( target, "9" );
  213. /* Test list_cut_position() - multi-entry list, move nothing */
  214. INIT_LIST_HEAD ( list );
  215. list_add_tail ( &list_tests[3].list, list );
  216. list_add_tail ( &list_tests[2].list, list );
  217. list_add_tail ( &list_tests[7].list, list );
  218. INIT_LIST_HEAD ( target );
  219. list_cut_position ( target, list, list );
  220. list_contents_ok ( list, "327" );
  221. list_contents_ok ( target, "" );
  222. /* Test list_cut_position() - multi-entry list, move some */
  223. INIT_LIST_HEAD ( list );
  224. INIT_LIST_HEAD ( target );
  225. list_add_tail ( &list_tests[8].list, list );
  226. list_add_tail ( &list_tests[0].list, list );
  227. list_add_tail ( &list_tests[9].list, list );
  228. list_add_tail ( &list_tests[3].list, list );
  229. list_add_tail ( &list_tests[2].list, list );
  230. list_cut_position ( target, list, &list_tests[0].list );
  231. list_contents_ok ( list, "932" );
  232. list_contents_ok ( target, "80" );
  233. /* Test list_cut_position() - multi-entry list, move everything */
  234. INIT_LIST_HEAD ( list );
  235. INIT_LIST_HEAD ( target );
  236. list_add_tail ( &list_tests[3].list, list );
  237. list_add_tail ( &list_tests[5].list, list );
  238. list_add_tail ( &list_tests[4].list, list );
  239. list_add_tail ( &list_tests[7].list, list );
  240. list_add_tail ( &list_tests[1].list, list );
  241. list_cut_position ( target, list, &list_tests[1].list );
  242. list_contents_ok ( list, "" );
  243. list_contents_ok ( target, "35471" );
  244. /* Test list_splice() - empty list */
  245. INIT_LIST_HEAD ( list );
  246. INIT_LIST_HEAD ( target );
  247. list_splice ( list, target );
  248. list_contents_ok ( list, "" );
  249. list_contents_ok ( target, "" );
  250. /* Test list_splice() - both lists empty */
  251. INIT_LIST_HEAD ( list );
  252. INIT_LIST_HEAD ( target );
  253. list_splice ( list, target );
  254. list_contents_ok ( target, "" );
  255. /* Test list_splice() - source list empty */
  256. INIT_LIST_HEAD ( list );
  257. INIT_LIST_HEAD ( target );
  258. list_add_tail ( &list_tests[1].list, target );
  259. list_add_tail ( &list_tests[3].list, target );
  260. list_splice ( list, &list_tests[1].list );
  261. list_contents_ok ( target, "13" );
  262. /* Test list_splice() - destination list empty */
  263. INIT_LIST_HEAD ( list );
  264. INIT_LIST_HEAD ( target );
  265. list_add_tail ( &list_tests[6].list, list );
  266. list_add_tail ( &list_tests[5].list, list );
  267. list_add_tail ( &list_tests[2].list, list );
  268. list_splice ( list, target );
  269. list_contents_ok ( target, "652" );
  270. /* Test list_splice() - both lists non-empty */
  271. INIT_LIST_HEAD ( list );
  272. INIT_LIST_HEAD ( target );
  273. list_add_tail ( &list_tests[8].list, list );
  274. list_add_tail ( &list_tests[4].list, list );
  275. list_add_tail ( &list_tests[5].list, list );
  276. list_add_tail ( &list_tests[1].list, target );
  277. list_add_tail ( &list_tests[9].list, target );
  278. list_splice ( list, &list_tests[1].list );
  279. list_contents_ok ( target, "18459" );
  280. /* Test list_splice_tail() - both lists empty */
  281. INIT_LIST_HEAD ( list );
  282. INIT_LIST_HEAD ( target );
  283. list_splice_tail ( list, target );
  284. list_contents_ok ( target, "" );
  285. /* Test list_splice_tail() - source list empty */
  286. INIT_LIST_HEAD ( list );
  287. INIT_LIST_HEAD ( target );
  288. list_add_tail ( &list_tests[5].list, target );
  289. list_splice_tail ( list, &list_tests[5].list );
  290. list_contents_ok ( target, "5" );
  291. /* Test list_splice_tail() - destination list empty */
  292. INIT_LIST_HEAD ( list );
  293. INIT_LIST_HEAD ( target );
  294. list_add_tail ( &list_tests[2].list, list );
  295. list_add_tail ( &list_tests[1].list, list );
  296. list_add_tail ( &list_tests[0].list, list );
  297. list_splice_tail ( list, target );
  298. list_contents_ok ( target, "210" );
  299. /* Test list_splice_tail() - both lists non-empty */
  300. INIT_LIST_HEAD ( list );
  301. INIT_LIST_HEAD ( target );
  302. list_add_tail ( &list_tests[9].list, list );
  303. list_add_tail ( &list_tests[5].list, list );
  304. list_add_tail ( &list_tests[7].list, list );
  305. list_add_tail ( &list_tests[2].list, target );
  306. list_add_tail ( &list_tests[4].list, target );
  307. list_splice_tail ( list, &list_tests[2].list );
  308. list_contents_ok ( target, "95724" );
  309. /* Test list_splice_init() */
  310. INIT_LIST_HEAD ( list );
  311. INIT_LIST_HEAD ( target );
  312. list_add_tail ( &list_tests[4].list, list );
  313. list_add_tail ( &list_tests[1].list, target );
  314. list_splice_init ( list, target );
  315. ok ( list_empty ( list ) );
  316. list_contents_ok ( list, "" );
  317. list_contents_ok ( target, "41" );
  318. /* Test list_splice_tail_init() */
  319. INIT_LIST_HEAD ( list );
  320. INIT_LIST_HEAD ( target );
  321. list_add_tail ( &list_tests[3].list, list );
  322. list_add_tail ( &list_tests[2].list, list );
  323. list_add_tail ( &list_tests[5].list, target );
  324. list_splice_tail_init ( list, &list_tests[5].list );
  325. ok ( list_empty ( list ) );
  326. list_contents_ok ( list, "" );
  327. list_contents_ok ( target, "325" );
  328. /* Test list_entry() */
  329. INIT_LIST_HEAD ( &list_tests[3].list ); // for list_check()
  330. ok ( list_entry ( &list_tests[3].list, struct list_test, list )
  331. == &list_tests[3] );
  332. /* Test list_first_entry() and list_last_entry() */
  333. INIT_LIST_HEAD ( list );
  334. list_add_tail ( &list_tests[9].list, list );
  335. list_add_tail ( &list_tests[5].list, list );
  336. list_add_tail ( &list_tests[6].list, list );
  337. ok ( list_first_entry ( list, struct list_test, list )
  338. == &list_tests[9] );
  339. ok ( list_last_entry ( list, struct list_test, list )
  340. == &list_tests[6] );
  341. list_del ( &list_tests[9].list );
  342. ok ( list_first_entry ( list, struct list_test, list )
  343. == &list_tests[5] );
  344. ok ( list_last_entry ( list, struct list_test, list )
  345. == &list_tests[6] );
  346. list_del ( &list_tests[6].list );
  347. ok ( list_first_entry ( list, struct list_test, list )
  348. == &list_tests[5] );
  349. ok ( list_last_entry ( list, struct list_test, list )
  350. == &list_tests[5] );
  351. list_del ( &list_tests[5].list );
  352. ok ( list_first_entry ( list, struct list_test, list ) == NULL );
  353. ok ( list_last_entry ( list, struct list_test, list ) == NULL );
  354. /* Test list_for_each() */
  355. INIT_LIST_HEAD ( list );
  356. list_add_tail ( &list_tests[6].list, list );
  357. list_add_tail ( &list_tests[7].list, list );
  358. list_add_tail ( &list_tests[3].list, list );
  359. list_iterate_ok ( list_for_each, "673", raw_pos, list );
  360. /* Test list_for_each_entry() and list_for_each_entry_reverse() */
  361. INIT_LIST_HEAD ( list );
  362. list_add_tail ( &list_tests[3].list, list );
  363. list_add_tail ( &list_tests[2].list, list );
  364. list_add_tail ( &list_tests[6].list, list );
  365. list_add_tail ( &list_tests[9].list, list );
  366. list_iterate_entry_ok ( list_for_each_entry, "3269",
  367. pos, list, list );
  368. list_iterate_entry_ok ( list_for_each_entry_reverse, "9623",
  369. pos, list, list );
  370. /* Test list_for_each_entry_safe() */
  371. INIT_LIST_HEAD ( list );
  372. list_add_tail ( &list_tests[2].list, list );
  373. list_add_tail ( &list_tests[4].list, list );
  374. list_add_tail ( &list_tests[1].list, list );
  375. {
  376. char *expected = "241";
  377. list_for_each_entry_safe ( pos, tmp, list, list ) {
  378. list_contents_ok ( list, expected );
  379. list_del ( &pos->list );
  380. expected++;
  381. list_contents_ok ( list, expected );
  382. }
  383. }
  384. ok ( list_empty ( list ) );
  385. /* Test list_for_each_entry_continue() and
  386. * list_for_each_entry_continue_reverse()
  387. */
  388. INIT_LIST_HEAD ( list );
  389. list_add_tail ( &list_tests[4].list, list );
  390. list_add_tail ( &list_tests[7].list, list );
  391. list_add_tail ( &list_tests[2].list, list );
  392. list_add_tail ( &list_tests[9].list, list );
  393. list_add_tail ( &list_tests[3].list, list );
  394. pos = &list_tests[7];
  395. list_iterate_entry_ok ( list_for_each_entry_continue, "293",
  396. pos, list, list );
  397. ok ( pos == list_entry ( list, struct list_test, list ) );
  398. list_iterate_entry_ok ( list_for_each_entry_continue, "47293",
  399. pos, list, list );
  400. pos = &list_tests[3];
  401. list_iterate_entry_ok ( list_for_each_entry_continue, "",
  402. pos, list, list );
  403. pos = &list_tests[2];
  404. list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "74",
  405. pos, list, list );
  406. ok ( pos == list_entry ( list, struct list_test, list ) );
  407. list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "39274",
  408. pos, list, list );
  409. pos = &list_tests[4];
  410. list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "",
  411. pos, list, list );
  412. /* Test list_contains() and list_contains_entry() */
  413. INIT_LIST_HEAD ( list );
  414. INIT_LIST_HEAD ( &list_tests[3].list );
  415. list_add ( &list_tests[8].list, list );
  416. list_add ( &list_tests[5].list, list );
  417. ok ( list_contains ( &list_tests[8].list, list ) );
  418. ok ( list_contains_entry ( &list_tests[8], list, list ) );
  419. ok ( list_contains ( &list_tests[5].list, list ) );
  420. ok ( list_contains_entry ( &list_tests[5], list, list ) );
  421. ok ( ! list_contains ( &list_tests[3].list, list ) );
  422. ok ( ! list_contains_entry ( &list_tests[3], list, list ) );
  423. /* Test list_check_contains_entry() */
  424. INIT_LIST_HEAD ( list );
  425. list_add ( &list_tests[4].list, list );
  426. list_add ( &list_tests[0].list, list );
  427. list_add ( &list_tests[3].list, list );
  428. list_check_contains_entry ( &list_tests[4], list, list );
  429. list_check_contains_entry ( &list_tests[0], list, list );
  430. list_check_contains_entry ( &list_tests[3], list, list );
  431. }
  432. /** List self-test */
  433. struct self_test list_test __self_test = {
  434. .name = "list",
  435. .exec = list_test_exec,
  436. };