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 18KB

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