tlist: Add tlist_next() and tlist_prev() functions
[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(60);
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         ok1(tlist_next(&parent.children, &c2, list) == NULL);
45         ok1(tlist_prev(&parent.children, &c2, list) == NULL);
46         /* Test tlist_check */
47         ok1(tlist_check(&parent.children, NULL));
48
49         c1.name = "c1";
50         tlist_add(&parent.children, &c1, list);
51         /* Test list_add and !list_empty. */
52         ok1(!tlist_empty(&parent.children));
53         ok1(c2.list.next == &parent.children.raw.n);
54         ok1(c2.list.prev == &c1.list);
55         ok1(parent.children.raw.n.next == &c1.list);
56         ok1(parent.children.raw.n.prev == &c2.list);
57         ok1(c1.list.next == &c2.list);
58         ok1(c1.list.prev == &parent.children.raw.n);
59         ok1(tlist_next(&parent.children, &c1, list) == &c2);
60         ok1(tlist_next(&parent.children, &c2, list) == NULL);
61         ok1(tlist_prev(&parent.children, &c2, list) == &c1);
62         ok1(tlist_prev(&parent.children, &c1, list) == NULL);
63         /* Test tlist_check */
64         ok1(tlist_check(&parent.children, NULL));
65
66         c3.name = "c3";
67         tlist_add_tail(&parent.children, &c3, list);
68         /* Test list_add_tail and !list_empty. */
69         ok1(!tlist_empty(&parent.children));
70         ok1(parent.children.raw.n.next == &c1.list);
71         ok1(parent.children.raw.n.prev == &c3.list);
72         ok1(c1.list.next == &c2.list);
73         ok1(c1.list.prev == &parent.children.raw.n);
74         ok1(c2.list.next == &c3.list);
75         ok1(c2.list.prev == &c1.list);
76         ok1(c3.list.next == &parent.children.raw.n);
77         ok1(c3.list.prev == &c2.list);
78         ok1(tlist_next(&parent.children, &c1, list) == &c2);
79         ok1(tlist_next(&parent.children, &c2, list) == &c3);
80         ok1(tlist_next(&parent.children, &c3, list) == NULL);
81         ok1(tlist_prev(&parent.children, &c3, list) == &c2);
82         ok1(tlist_prev(&parent.children, &c2, list) == &c1);
83         ok1(tlist_prev(&parent.children, &c1, list) == NULL);
84         /* Test tlist_check */
85         ok1(tlist_check(&parent.children, NULL));
86
87         /* Test tlist_top */
88         ok1(tlist_top(&parent.children, list) == &c1);
89
90         /* Test list_tail */
91         ok1(tlist_tail(&parent.children, list) == &c3);
92
93         /* Test tlist_for_each. */
94         i = 0;
95         tlist_for_each(&parent.children, c, list) {
96                 switch (i++) {
97                 case 0:
98                         ok1(c == &c1);
99                         break;
100                 case 1:
101                         ok1(c == &c2);
102                         break;
103                 case 2:
104                         ok1(c == &c3);
105                         break;
106                 }
107                 if (i > 2)
108                         break;
109         }
110         ok1(i == 3);
111
112         /* Test tlist_for_each_rev. */
113         i = 0;
114         tlist_for_each_rev(&parent.children, c, list) {
115                 switch (i++) {
116                 case 0:
117                         ok1(c == &c3);
118                         break;
119                 case 1:
120                         ok1(c == &c2);
121                         break;
122                 case 2:
123                         ok1(c == &c1);
124                         break;
125                 }
126                 if (i > 2)
127                         break;
128         }
129         ok1(i == 3);
130
131         /* Test tlist_for_each_safe, tlist_del and tlist_del_from. */
132         i = 0;
133         tlist_for_each_safe(&parent.children, c, n, list) {
134                 switch (i++) {
135                 case 0:
136                         ok1(c == &c1);  
137                         tlist_del(c, list);
138                         break;
139                 case 1:
140                         ok1(c == &c2);
141                         tlist_del_from(&parent.children, c, list);
142                         break;
143                 case 2:
144                         ok1(c == &c3);
145                         tlist_del_from(&parent.children, c, list);
146                         break;
147                 }
148                 ok1(tlist_check(&parent.children, NULL));
149                 if (i > 2)
150                         break;
151         }
152         ok1(i == 3);
153         ok1(tlist_empty(&parent.children));
154
155         /* Test list_top/list_tail on empty list. */
156         ok1(tlist_top(&parent.children, list) == (struct child *)NULL);
157         ok1(tlist_tail(&parent.children, list) == (struct child *)NULL);
158         return exit_status();
159 }