1 /* Make sure macros only evaluate their args once. */
2 #include <ccan/list/list.h>
3 #include <ccan/tap/tap.h>
4 #include <ccan/list/list.c>
8 struct list_head children;
9 unsigned int num_children;
15 struct list_node list;
18 static LIST_HEAD(static_list);
20 #define ref(obj, counter) ((counter)++, (obj))
25 struct child c1, c2, c3, *c, *n;
27 unsigned int static_count = 0, parent_count = 0, list_count = 0,
29 struct list_head list = LIST_HEAD_INIT(list);
32 /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
33 ok1(list_empty(ref(&static_list, static_count)));
34 ok1(static_count == 1);
35 ok1(list_check(ref(&static_list, static_count), NULL));
36 ok1(static_count == 2);
37 ok1(list_empty(ref(&list, list_count)));
39 ok1(list_check(ref(&list, list_count), NULL));
42 parent.num_children = 0;
43 list_head_init(ref(&parent.children, parent_count));
44 ok1(parent_count == 1);
45 /* Test list_head_init */
46 ok1(list_empty(ref(&parent.children, parent_count)));
47 ok1(parent_count == 2);
48 ok1(list_check(ref(&parent.children, parent_count), NULL));
49 ok1(parent_count == 3);
52 list_add(ref(&parent.children, parent_count), &c2.list);
53 ok1(parent_count == 4);
54 /* Test list_add and !list_empty. */
55 ok1(!list_empty(ref(&parent.children, parent_count)));
56 ok1(parent_count == 5);
57 ok1(c2.list.next == &parent.children.n);
58 ok1(c2.list.prev == &parent.children.n);
59 ok1(parent.children.n.next == &c2.list);
60 ok1(parent.children.n.prev == &c2.list);
62 ok1(list_check(ref(&parent.children, parent_count), NULL));
63 ok1(parent_count == 6);
66 list_add(ref(&parent.children, parent_count), &c1.list);
67 ok1(parent_count == 7);
68 /* Test list_add and !list_empty. */
69 ok1(!list_empty(ref(&parent.children, parent_count)));
70 ok1(parent_count == 8);
71 ok1(c2.list.next == &parent.children.n);
72 ok1(c2.list.prev == &c1.list);
73 ok1(parent.children.n.next == &c1.list);
74 ok1(parent.children.n.prev == &c2.list);
75 ok1(c1.list.next == &c2.list);
76 ok1(c1.list.prev == &parent.children.n);
78 ok1(list_check(ref(&parent.children, parent_count), NULL));
79 ok1(parent_count == 9);
82 list_add_tail(ref(&parent.children, parent_count), &c3.list);
83 ok1(parent_count == 10);
84 /* Test list_add_tail and !list_empty. */
85 ok1(!list_empty(ref(&parent.children, parent_count)));
86 ok1(parent_count == 11);
87 ok1(parent.children.n.next == &c1.list);
88 ok1(parent.children.n.prev == &c3.list);
89 ok1(c1.list.next == &c2.list);
90 ok1(c1.list.prev == &parent.children.n);
91 ok1(c2.list.next == &c3.list);
92 ok1(c2.list.prev == &c1.list);
93 ok1(c3.list.next == &parent.children.n);
94 ok1(c3.list.prev == &c2.list);
96 ok1(list_check(ref(&parent.children, parent_count), NULL));
97 ok1(parent_count == 12);
99 /* Test list_check_node */
100 ok1(list_check_node(&c1.list, NULL));
101 ok1(list_check_node(&c2.list, NULL));
102 ok1(list_check_node(&c3.list, NULL));
105 ok1(list_top(ref(&parent.children, parent_count), struct child, list) == &c1);
106 ok1(parent_count == 13);
109 ok1(list_tail(ref(&parent.children, parent_count), struct child, list) == &c3);
110 ok1(parent_count == 14);
112 /* Test list_for_each. */
114 list_for_each(&parent.children, c, list) {
131 /* Test list_for_each_safe, list_del and list_del_from. */
133 list_for_each_safe(&parent.children, c, n, list) {
137 list_del(ref(&c->list, node_count));
138 ok1(node_count == 1);
142 list_del_from(ref(&parent.children, parent_count),
143 ref(&c->list, node_count));
144 ok1(node_count == 2);
148 list_del_from(ref(&parent.children, parent_count),
149 ref(&c->list, node_count));
150 ok1(node_count == 3);
153 ok1(list_check(ref(&parent.children, parent_count), NULL));
158 ok1(parent_count == 19);
159 ok1(list_empty(ref(&parent.children, parent_count)));
160 ok1(parent_count == 20);
162 /* Test list_top/list_tail on empty list. */
163 ok1(list_top(ref(&parent.children, parent_count), struct child, list) == NULL);
164 ok1(parent_count == 21);
165 ok1(list_tail(ref(&parent.children, parent_count), struct child, list) == NULL);
166 ok1(parent_count == 22);
167 return exit_status();