tlist: implement tlist_for_each_rev
[ccan] / ccan / tlist / test / run.c
1 #define CCAN_LIST_DEBUG 1
2 #include <ccan/tlist/tlist.h>
3 #include <ccan/tap/tap.h>
4
5 TLIST_TYPE(children, struct child);
6
7 struct parent {
8         const char *name;
9         struct tlist_children children;
10         unsigned int num_children;
11 };
12
13 struct child {
14         const char *name;
15         struct list_node list;
16 };
17
18 int main(int argc, char *argv[])
19 {
20         struct parent parent;
21         struct child c1, c2, c3, *c, *n;
22         unsigned int i;
23         struct tlist_children tlist = TLIST_INIT(tlist);
24
25         plan_tests(48);
26         /* Test TLIST_INIT, and tlist_empty */
27         ok1(tlist_empty(&tlist));
28         ok1(tlist_check(&tlist, NULL));
29
30         parent.num_children = 0;
31         tlist_init(&parent.children);
32         /* Test tlist_init */
33         ok1(tlist_empty(&parent.children));
34         ok1(tlist_check(&parent.children, NULL));
35
36         c2.name = "c2";
37         tlist_add(&parent.children, &c2, list);
38         /* Test tlist_add and !tlist_empty. */
39         ok1(!tlist_empty(&parent.children));
40         ok1(c2.list.next == &parent.children.raw.n);
41         ok1(c2.list.prev == &parent.children.raw.n);
42         ok1(parent.children.raw.n.next == &c2.list);
43         ok1(parent.children.raw.n.prev == &c2.list);
44         /* Test tlist_check */
45         ok1(tlist_check(&parent.children, NULL));
46
47         c1.name = "c1";
48         tlist_add(&parent.children, &c1, list);
49         /* Test list_add and !list_empty. */
50         ok1(!tlist_empty(&parent.children));
51         ok1(c2.list.next == &parent.children.raw.n);
52         ok1(c2.list.prev == &c1.list);
53         ok1(parent.children.raw.n.next == &c1.list);
54         ok1(parent.children.raw.n.prev == &c2.list);
55         ok1(c1.list.next == &c2.list);
56         ok1(c1.list.prev == &parent.children.raw.n);
57         /* Test tlist_check */
58         ok1(tlist_check(&parent.children, NULL));
59
60         c3.name = "c3";
61         tlist_add_tail(&parent.children, &c3, list);
62         /* Test list_add_tail and !list_empty. */
63         ok1(!tlist_empty(&parent.children));
64         ok1(parent.children.raw.n.next == &c1.list);
65         ok1(parent.children.raw.n.prev == &c3.list);
66         ok1(c1.list.next == &c2.list);
67         ok1(c1.list.prev == &parent.children.raw.n);
68         ok1(c2.list.next == &c3.list);
69         ok1(c2.list.prev == &c1.list);
70         ok1(c3.list.next == &parent.children.raw.n);
71         ok1(c3.list.prev == &c2.list);
72         /* Test tlist_check */
73         ok1(tlist_check(&parent.children, NULL));
74
75         /* Test tlist_top */
76         ok1(tlist_top(&parent.children, struct child, list) == &c1);
77
78         /* Test list_tail */
79         ok1(tlist_tail(&parent.children, struct child, list) == &c3);
80
81         /* Test tlist_for_each. */
82         i = 0;
83         tlist_for_each(&parent.children, c, list) {
84                 switch (i++) {
85                 case 0:
86                         ok1(c == &c1);
87                         break;
88                 case 1:
89                         ok1(c == &c2);
90                         break;
91                 case 2:
92                         ok1(c == &c3);
93                         break;
94                 }
95                 if (i > 2)
96                         break;
97         }
98         ok1(i == 3);
99
100         /* Test tlist_for_each_rev. */
101         i = 0;
102         tlist_for_each_rev(&parent.children, c, list) {
103                 switch (i++) {
104                 case 0:
105                         ok1(c == &c3);
106                         break;
107                 case 1:
108                         ok1(c == &c2);
109                         break;
110                 case 2:
111                         ok1(c == &c1);
112                         break;
113                 }
114                 if (i > 2)
115                         break;
116         }
117         ok1(i == 3);
118
119         /* Test tlist_for_each_safe, tlist_del and tlist_del_from. */
120         i = 0;
121         tlist_for_each_safe(&parent.children, c, n, list) {
122                 switch (i++) {
123                 case 0:
124                         ok1(c == &c1);  
125                         tlist_del(c, list);
126                         break;
127                 case 1:
128                         ok1(c == &c2);
129                         tlist_del_from(&parent.children, c, list);
130                         break;
131                 case 2:
132                         ok1(c == &c3);
133                         tlist_del_from(&parent.children, c, list);
134                         break;
135                 }
136                 ok1(tlist_check(&parent.children, NULL));
137                 if (i > 2)
138                         break;
139         }
140         ok1(i == 3);
141         ok1(tlist_empty(&parent.children));
142
143         /* Test list_top/list_tail on empty list. */
144         ok1(tlist_top(&parent.children, struct child, list) == NULL);
145         ok1(tlist_tail(&parent.children, struct child, list) == NULL);
146         return exit_status();
147 }