1 /*
2 * Copyright (c) 2019 LK Trusty Authors. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <lk/list.h>
25
26 #include "gtest/gtest.h"
27
28 /**
29 * CheckListArray - check that a list contains specific items.
30 * @list: The list to check.
31 * @items: Array with expected items.
32 * @count: Number if entries in @items, and expected number of entries in
33 * @list.
34 *
35 * Check that @list contains the all the entries in @items, in the same order,
36 * and no other entries. Also check that head, tail, next and prev functions
37 * return the expected entries in @items.
38 */
CheckListArray(struct list_node * list,struct list_node * items[],int count)39 static void CheckListArray(struct list_node *list, struct list_node *items[],
40 int count) {
41 struct list_node *node;
42 int i = 0;
43
44 struct list_node *head_item = count ? items[0] : NULL;
45 EXPECT_EQ(list_peek_head(list), head_item) << "List has wrong head";
46
47 struct list_node *tail_item = count ? items[count - 1] : NULL;
48 EXPECT_EQ(list_peek_tail(list), tail_item) << "List has wrong tail";
49
50 list_for_every(list, node) {
51 ASSERT_GT(count, i) << "List has more items than expected";
52 EXPECT_EQ(node, items[i]) << "Wrong entry as index " << i;
53
54 struct list_node *prev_item = i > 0 ? items[i - 1] : NULL;
55 EXPECT_EQ(list_prev(list, node), prev_item) <<
56 "List has wrong back pointer at index " << i;
57
58 struct list_node *next_item = i < count - 1 ? items[i + 1] : NULL;
59 EXPECT_EQ(list_next(list, node), next_item) <<
60 "List has wrong next pointer at index " << i;
61 i++;
62 }
63 EXPECT_EQ(i, count) << "List has fewer items than expected";
64 }
65
66 #define ArraySize(a) (sizeof(a) / sizeof((a)[0]))
67
68 /**
69 * CheckList - Helper macro to call CheckListArray.
70 */
71 #define CheckList(list, items...) { \
72 SCOPED_TRACE("CheckList"); \
73 struct list_node *itemarray[] = {items}; \
74 CheckListArray(list, itemarray, ArraySize(itemarray)); \
75 }
76
77 /**
78 * DefineEmptyList - Helper macro to define and initialize a list.
79 */
80 #define DefineEmptyList(list) \
81 struct list_node list = LIST_INITIAL_VALUE(list);
82
83 /**
84 * DefineAndAddListItem - Helper macro to define and initialize a list entry and
85 * add it to a list.
86 */
87 #define DefineAndAddListItem(list, item) \
88 struct list_node item = LIST_INITIAL_CLEARED_VALUE; \
89 list_add_tail(&list, &item);
90
91 /**
92 * DefineListWith1Item - Helper macro to define and initialize a list with 1
93 * item.
94 */
95 #define DefineListWith1Item(list, item1) \
96 DefineEmptyList(list) \
97 DefineAndAddListItem(list, item1) \
98 CheckList(&list, &item1)
99
100 /**
101 * DefineListWith2Items - Helper macro to define and initialize a list with 2
102 * items.
103 */
104 #define DefineListWith2Items(list, item1, item2) \
105 DefineListWith1Item(list, item1) \
106 DefineAndAddListItem(list, item2) \
107 CheckList(&list, &item1, &item2)
108
109 /**
110 * DefineListWith3Items - Helper macro to define and initialize a list with 3
111 * items.
112 */
113 #define DefineListWith3Items(list, item1, item2, item3) \
114 DefineListWith2Items(list, item1, item2) \
115 DefineAndAddListItem(list, item3) \
116 CheckList(&list, &item1, &item2, &item3)
117
118 /* Smoke test 3 list init methods */
TEST(ListTest,ListInitialValue)119 TEST(ListTest, ListInitialValue) {
120 struct list_node list = LIST_INITIAL_VALUE(list);
121 EXPECT_TRUE(list_in_list(&list));
122 EXPECT_TRUE(list_is_empty(&list));
123 CheckList(&list);
124 }
125
TEST(ListTest,ListInitialClearedValue)126 TEST(ListTest, ListInitialClearedValue) {
127 struct list_node list = LIST_INITIAL_CLEARED_VALUE;
128 EXPECT_FALSE(list_in_list(&list));
129 }
130
TEST(ListTest,ListInitialize)131 TEST(ListTest, ListInitialize) {
132 struct list_node list;
133 list_initialize(&list);
134 EXPECT_TRUE(list_in_list(&list));
135 EXPECT_TRUE(list_is_empty(&list));
136 }
137
138 /* Test 4 list add methods */
TEST(ListTest,ListAddHead)139 TEST(ListTest, ListAddHead) {
140 struct list_node list = LIST_INITIAL_VALUE(list);
141 struct list_node item1 = LIST_INITIAL_CLEARED_VALUE;
142 struct list_node item2 = LIST_INITIAL_CLEARED_VALUE;
143
144 list_add_head(&list, &item1);
145 CheckList(&list, &item1);
146
147 list_add_head(&list, &item2);
148 CheckList(&list, &item2, &item1);
149 }
150
TEST(ListTest,ListAddAfterLast)151 TEST(ListTest, ListAddAfterLast) {
152 DefineListWith1Item(list, item1);
153 struct list_node item2 = LIST_INITIAL_CLEARED_VALUE;
154
155 list_add_after(&item1, &item2);
156 CheckList(&list, &item1, &item2);
157 }
158
TEST(ListTest,ListAddAfterNotLast)159 TEST(ListTest, ListAddAfterNotLast) {
160 DefineListWith2Items(list, item1, item2);
161 struct list_node item3 = LIST_INITIAL_CLEARED_VALUE;
162
163 list_add_after(&item1, &item3);
164 CheckList(&list, &item1, &item3, &item2);
165 }
166
TEST(ListTest,ListAddTail)167 TEST(ListTest, ListAddTail) {
168 struct list_node list = LIST_INITIAL_VALUE(list);
169 struct list_node item1 = LIST_INITIAL_CLEARED_VALUE;
170 struct list_node item2 = LIST_INITIAL_CLEARED_VALUE;
171
172 list_add_tail(&list, &item1);
173 CheckList(&list, &item1);
174
175 list_add_tail(&list, &item2);
176 CheckList(&list, &item1, &item2);
177 }
178
TEST(ListTest,ListAddBeforeHead)179 TEST(ListTest, ListAddBeforeHead) {
180 DefineListWith1Item(list, item1);
181 struct list_node item2 = LIST_INITIAL_CLEARED_VALUE;
182
183 list_add_before(&item1, &item2);
184 CheckList(&list, &item2, &item1);
185 }
186
TEST(ListTest,ListAddBeforeNotHead)187 TEST(ListTest, ListAddBeforeNotHead) {
188 DefineListWith2Items(list, item1, item2);
189 struct list_node item3 = LIST_INITIAL_CLEARED_VALUE;
190
191 list_add_before(&item2, &item3);
192 CheckList(&list, &item1, &item3, &item2);
193 }
194
195 /* Test list delete 4 possible configurations of prev and next entries */
TEST(ListTest,ListDeleteOnly)196 TEST(ListTest, ListDeleteOnly) {
197 DefineListWith1Item(list, item);
198 list_delete(&item);
199 EXPECT_FALSE(list_in_list(&item));
200 CheckList(&list);
201 }
202
TEST(ListTest,ListDeleteFirst)203 TEST(ListTest, ListDeleteFirst) {
204 DefineListWith2Items(list, item1, item2);
205 list_delete(&item1);
206 EXPECT_FALSE(list_in_list(&item1));
207 CheckList(&list, &item2);
208 }
209
TEST(ListTest,ListDeleteLast)210 TEST(ListTest, ListDeleteLast) {
211 DefineListWith2Items(list, item1, item2);
212 list_delete(&item2);
213 EXPECT_FALSE(list_in_list(&item2));
214 CheckList(&list, &item1);
215 }
216
TEST(ListTest,ListDeleteMiddle)217 TEST(ListTest, ListDeleteMiddle) {
218 DefineListWith3Items(list, item1, item2, item3);
219 list_delete(&item2);
220 EXPECT_FALSE(list_in_list(&item2));
221 CheckList(&list, &item1, &item3);
222 }
223
224 /*
225 * Test list_remove_head with 3 possible configurations of empty list, head is
226 * last entry, and head is not the last entry.
227 */
TEST(ListTest,ListRemoveHead)228 TEST(ListTest, ListRemoveHead) {
229 DefineListWith2Items(list, item1, item2);
230 struct list_node *node = list_remove_head(&list);
231 EXPECT_EQ(node, &item1);
232 CheckList(&list, &item2);
233 node = list_remove_head(&list);
234 EXPECT_EQ(node, &item2);
235 CheckList(&list);
236 node = list_remove_head(&list);
237 EXPECT_EQ(node, nullptr);
238 CheckList(&list);
239 }
240
241 /*
242 * Test list_remove_tail with 3 possible configurations of empty list, tail is
243 * first entry, and tail is not the first entry.
244 */
TEST(ListTest,ListRemoveTail)245 TEST(ListTest, ListRemoveTail) {
246 DefineListWith2Items(list, item1, item2);
247 struct list_node *node = list_remove_tail(&list);
248 EXPECT_EQ(node, &item2);
249 CheckList(&list, &item1);
250 node = list_remove_tail(&list);
251 EXPECT_EQ(node, &item1);
252 CheckList(&list);
253 node = list_remove_tail(&list);
254 EXPECT_EQ(node, nullptr);
255 CheckList(&list);
256 }
257
258 /*
259 * Test list_peek_head with and without entries in the list.
260 * Use 2 entries to separate tail and head in non-empty test.
261 */
TEST(ListTest,ListPeekHeadEmpty)262 TEST(ListTest, ListPeekHeadEmpty) {
263 struct list_node list = LIST_INITIAL_VALUE(list);
264 struct list_node *node = list_peek_head(&list);
265 EXPECT_EQ(node, nullptr);
266 }
267
TEST(ListTest,ListPeekHeadNotEmpty)268 TEST(ListTest, ListPeekHeadNotEmpty) {
269 DefineListWith2Items(list, item1, item2);
270 struct list_node *node = list_peek_head(&list);
271 EXPECT_EQ(node, &item1);
272 }
273
274 /*
275 * Test list_peek_tail with and without entries in the list.
276 * Use 2 entries to separate tail and head in non-empty test.
277 */
TEST(ListTest,ListPeekTailEmpty)278 TEST(ListTest, ListPeekTailEmpty) {
279 struct list_node list = LIST_INITIAL_VALUE(list);
280 struct list_node *node = list_peek_tail(&list);
281 EXPECT_EQ(node, nullptr);
282 }
283
TEST(ListTest,ListPeekTailNotEmpty)284 TEST(ListTest, ListPeekTailNotEmpty) {
285 DefineListWith2Items(list, item1, item2);
286 struct list_node *node = list_peek_tail(&list);
287 EXPECT_EQ(node, &item2);
288 }
289
290 /* Test list navigation functions. */
TEST(ListTest,ListPrevHead)291 TEST(ListTest, ListPrevHead) {
292 /*
293 * Calling list_prev on the head should return NULL.
294 */
295 DefineListWith2Items(list, item1, item2);
296 struct list_node *node = list_prev(&list, &item1);
297 EXPECT_EQ(node, nullptr);
298 }
299
TEST(ListTest,ListPrevNotHead)300 TEST(ListTest, ListPrevNotHead) {
301 /*
302 * Calling list_prev on entries other than the head should return the
303 * previous entry.
304 */
305 DefineListWith2Items(list, item1, item2);
306 struct list_node *node = list_prev(&list, &item2);
307 EXPECT_EQ(node, &item1);
308 }
309
TEST(ListTest,ListPrevWrapHead)310 TEST(ListTest, ListPrevWrapHead) {
311 /*
312 * Calling list_prev_wrap on the head should return the tail.
313 */
314 DefineListWith2Items(list, item1, item2);
315 struct list_node *node = list_prev_wrap(&list, &item1);
316 EXPECT_EQ(node, &item2);
317 }
318
TEST(ListTest,ListPrevWrapNotHead)319 TEST(ListTest, ListPrevWrapNotHead) {
320 /*
321 * Calling list_prev_wrap on entries other than the head should return the
322 * previous entry (same as list_prev).
323 */
324 DefineListWith2Items(list, item1, item2);
325 struct list_node *node = list_prev_wrap(&list, &item2);
326 EXPECT_EQ(node, &item1);
327 }
328
TEST(ListTest,ListPrevWrapEmpty)329 TEST(ListTest, ListPrevWrapEmpty) {
330 /*
331 * Calling list_prev_wrap on the list itself, instead of an entry does not
332 * appear to be a useful operation, but the implemention allows it and
333 * returns NULL in that case.
334 */
335 DefineEmptyList(list);
336 struct list_node *node = list_prev_wrap(&list, &list);
337 EXPECT_EQ(node, nullptr);
338 }
339
TEST(ListTest,ListNextHead)340 TEST(ListTest, ListNextHead) {
341 /*
342 * Calling list_next on the tail should return NULL.
343 */
344 DefineListWith2Items(list, item1, item2);
345 struct list_node *node = list_next(&list, &item2);
346 EXPECT_EQ(node, nullptr);
347 }
348
TEST(ListTest,ListNextNotTail)349 TEST(ListTest, ListNextNotTail) {
350 /*
351 * Calling list_next on entries other than the tail should return the next
352 * entry.
353 */
354 DefineListWith2Items(list, item1, item2);
355 struct list_node *node = list_next(&list, &item1);
356 EXPECT_EQ(node, &item2);
357 }
358
TEST(ListTest,ListNextWrapTail)359 TEST(ListTest, ListNextWrapTail) {
360 /*
361 * Calling list_next_wrap on the tail should return the head.
362 */
363 DefineListWith2Items(list, item1, item2);
364 struct list_node *node = list_next_wrap(&list, &item2);
365 EXPECT_EQ(node, &item1);
366 }
367
TEST(ListTest,ListNextWrapNotTail)368 TEST(ListTest, ListNextWrapNotTail) {
369 /*
370 * Calling list_next_wrap on entries other than the tail should return the
371 * next entry (same as list_next).
372 */
373 DefineListWith2Items(list, item1, item2);
374 struct list_node *node = list_next_wrap(&list, &item1);
375 EXPECT_EQ(node, &item2);
376 }
377
TEST(ListTest,ListNextWrapEmpty)378 TEST(ListTest, ListNextWrapEmpty) {
379 /*
380 * Calling list_next_wrap on the list itself, instead of an entry does not
381 * appear to be a useful operation, but the implemention allows it and
382 * returns NULL in that case.
383 */
384 DefineEmptyList(list);
385 struct list_node *node = list_next_wrap(&list, &list);
386 EXPECT_EQ(node, nullptr);
387 }
388
389 /* Test list iterators */
TEST(ListTest,ListForEvery)390 TEST(ListTest, ListForEvery) {
391 /*
392 * list_for_every should return every entry one by one.
393 */
394 DefineListWith2Items(list, item1, item2);
395 struct list_node *itemarray[] = {&item1, &item2};
396 size_t i = 0;
397 struct list_node *node;
398 list_for_every(&list, node) {
399 ASSERT_LT(i, countof(itemarray));
400 EXPECT_EQ(node, itemarray[i]);
401 i++;
402 }
403 EXPECT_EQ(i, countof(itemarray));
404 }
405
TEST(ListTest,ListForEverySafe)406 TEST(ListTest, ListForEverySafe) {
407 /*
408 * list_for_every_safe should return every entry one by one even if the
409 * current entry is removed (not tested here).
410 */
411 DefineListWith2Items(list, item1, item2);
412 struct list_node *itemarray[] = {&item1, &item2};
413 size_t i = 0;
414 struct list_node *node;
415 struct list_node *tmp_node;
416 list_for_every_safe(&list, node, tmp_node) {
417 ASSERT_LT(i, countof(itemarray));
418 EXPECT_EQ(node, itemarray[i]);
419 i++;
420 }
421 EXPECT_EQ(i, countof(itemarray));
422 }
423
TEST(ListTest,ListForEverySafeDeleteAll)424 TEST(ListTest, ListForEverySafeDeleteAll) {
425 /*
426 * list_for_every_safe should return every entry one by one even if the
427 * current entry is removed (tested here).
428 */
429 DefineListWith2Items(list, item1, item2);
430 struct list_node *itemarray[] = {&item1, &item2};
431 size_t i = 0;
432 struct list_node *node;
433 struct list_node *tmp_node;
434 list_for_every_safe(&list, node, tmp_node) {
435 ASSERT_LT(i, countof(itemarray));
436 EXPECT_EQ(node, itemarray[i]);
437 list_delete(node);
438 i++;
439 }
440 EXPECT_EQ(i, countof(itemarray));
441 CheckList(&list);
442 }
443
TEST(ListTest,ListForEverySafeDeleteSome)444 TEST(ListTest, ListForEverySafeDeleteSome) {
445 /*
446 * list_for_every_safe should return every entry one by one even if the
447 * current entry is removed (tested here).
448 */
449 DefineListWith3Items(list, item1, item2, item3);
450 struct list_node *itemarray[] = {&item1, &item2, &item3};
451 size_t i = 0;
452 struct list_node *node;
453 struct list_node *tmp_node;
454 list_for_every_safe(&list, node, tmp_node) {
455 ASSERT_LT(i, countof(itemarray));
456 EXPECT_EQ(node, itemarray[i]);
457 if (i != 1) {
458 list_delete(node);
459 }
460 i++;
461 }
462 EXPECT_EQ(i, countof(itemarray));
463 CheckList(&list, &item2);
464 }
465
466 /* Test list empty and count functions */
TEST(ListTest,ListIsEmptyEmpty)467 TEST(ListTest, ListIsEmptyEmpty) {
468 DefineEmptyList(list);
469 EXPECT_TRUE(list_is_empty(&list));
470 }
471
TEST(ListTest,ListIsEmptyNotEmpty)472 TEST(ListTest, ListIsEmptyNotEmpty) {
473 DefineListWith1Item(list, item);
474 EXPECT_FALSE(list_is_empty(&list));
475 }
476
TEST(ListTest,ListLengthEmpty)477 TEST(ListTest, ListLengthEmpty) {
478 DefineEmptyList(list);
479 EXPECT_EQ(list_length(&list), 0U);
480 }
481
TEST(ListTest,ListLength1)482 TEST(ListTest, ListLength1) {
483 DefineListWith1Item(list, item);
484 EXPECT_EQ(list_length(&list), 1U);
485 }
486
TEST(ListTest,ListLength2)487 TEST(ListTest, ListLength2) {
488 DefineListWith2Items(list, item1, item2);
489 EXPECT_EQ(list_length(&list), 2U);
490 }
491
492 /* Test list splice operations */
TEST(ListTest,ListSpliceTailBothEmpty)493 TEST(ListTest, ListSpliceTailBothEmpty) {
494 DefineEmptyList(list1);
495 DefineEmptyList(list2);
496 list_splice_tail(&list1, &list2);
497 CheckList(&list1);
498 CheckList(&list2);
499 }
500
TEST(ListTest,ListSpliceTailSrcEmpty)501 TEST(ListTest, ListSpliceTailSrcEmpty) {
502 DefineListWith2Items(list1, item1, item2);
503 DefineEmptyList(list2);
504 list_splice_tail(&list1, &list2);
505 CheckList(&list1, &item1, &item2);
506 CheckList(&list2);
507 }
508
TEST(ListTest,ListSpliceTailSrc1Item)509 TEST(ListTest, ListSpliceTailSrc1Item) {
510 DefineListWith2Items(list1, item1, item2);
511 DefineListWith1Item(list2, item3);
512 list_splice_tail(&list1, &list2);
513 CheckList(&list1, &item1, &item2, &item3);
514 CheckList(&list2);
515 }
516
TEST(ListTest,ListSpliceTailDestEmpty)517 TEST(ListTest, ListSpliceTailDestEmpty) {
518 DefineEmptyList(list1);
519 DefineListWith2Items(list2, item1, item2);
520 list_splice_tail(&list1, &list2);
521 CheckList(&list1, &item1, &item2);
522 CheckList(&list2);
523 }
524
TEST(ListTest,ListSpliceTailDest1Item)525 TEST(ListTest, ListSpliceTailDest1Item) {
526 DefineListWith1Item(list1, item1);
527 DefineListWith2Items(list2, item2, item3);
528 list_splice_tail(&list1, &list2);
529 CheckList(&list1, &item1, &item2, &item3);
530 CheckList(&list2);
531 }
532
TEST(ListTest,ListSpliceTail)533 TEST(ListTest, ListSpliceTail) {
534 DefineListWith2Items(list1, item1, item2);
535 DefineListWith2Items(list2, item3, item4);
536 list_splice_tail(&list1, &list2);
537 CheckList(&list1, &item1, &item2, &item3, &item4);
538 CheckList(&list2);
539 }
540
TEST(ListTest,ListSpliceHeadBothEmpty)541 TEST(ListTest, ListSpliceHeadBothEmpty) {
542 DefineEmptyList(list1);
543 DefineEmptyList(list2);
544 list_splice_head(&list1, &list2);
545 CheckList(&list1);
546 CheckList(&list2);
547 }
548
TEST(ListTest,ListSpliceHeadSrcEmpty)549 TEST(ListTest, ListSpliceHeadSrcEmpty) {
550 DefineListWith2Items(list1, item1, item2);
551 DefineEmptyList(list2);
552 list_splice_head(&list1, &list2);
553 CheckList(&list1, &item1, &item2);
554 CheckList(&list2);
555 }
556
TEST(ListTest,ListSpliceHeadSrc1Item)557 TEST(ListTest, ListSpliceHeadSrc1Item) {
558 DefineListWith2Items(list1, item2, item3);
559 DefineListWith1Item(list2, item1);
560 list_splice_head(&list1, &list2);
561 CheckList(&list1, &item1, &item2, &item3);
562 CheckList(&list2);
563 }
564
TEST(ListTest,ListSpliceHeadDestEmpty)565 TEST(ListTest, ListSpliceHeadDestEmpty) {
566 DefineEmptyList(list1);
567 DefineListWith2Items(list2, item1, item2);
568 list_splice_head(&list1, &list2);
569 CheckList(&list1, &item1, &item2);
570 CheckList(&list2);
571 }
572
TEST(ListTest,ListSpliceHeadDest1Item)573 TEST(ListTest, ListSpliceHeadDest1Item) {
574 DefineListWith1Item(list1, item3);
575 DefineListWith2Items(list2, item1, item2);
576 list_splice_head(&list1, &list2);
577 CheckList(&list1, &item1, &item2, &item3);
578 CheckList(&list2);
579 }
580
TEST(ListTest,ListSpliceHead)581 TEST(ListTest, ListSpliceHead) {
582 DefineListWith2Items(list1, item3, item4);
583 DefineListWith2Items(list2, item1, item2);
584 list_splice_head(&list1, &list2);
585 CheckList(&list1, &item1, &item2, &item3, &item4);
586 CheckList(&list2);
587 }
588
TEST(ListTest,ListSpliceAfter)589 TEST(ListTest, ListSpliceAfter) {
590 DefineListWith2Items(list1, item1, item4);
591 DefineListWith2Items(list2, item2, item3);
592 list_splice_after(&item1, &list2);
593 CheckList(&list1, &item1, &item2, &item3, &item4);
594 CheckList(&list2);
595 }
596
TEST(ListTest,ListSpliceBefore)597 TEST(ListTest, ListSpliceBefore) {
598 DefineListWith2Items(list1, item1, item4);
599 DefineListWith2Items(list2, item2, item3);
600 list_splice_before(&item4, &list2);
601 CheckList(&list1, &item1, &item2, &item3, &item4);
602 CheckList(&list2);
603 }
604