tlist: typesafe variant of list module.
[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(44);
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_safe, tlist_del and tlist_del_from. */
101         i = 0;
102         tlist_for_each_safe(&parent.children, c, n, list) {
103                 switch (i++) {
104                 case 0:
105                         ok1(c == &c1);  
106                         tlist_del(c, list);
107                         break;
108                 case 1:
109                         ok1(c == &c2);
110                         tlist_del_from(&parent.children, c, list);
111                         break;
112                 case 2:
113                         ok1(c == &c3);
114                         tlist_del_from(&parent.children, c, list);
115                         break;
116                 }
117                 ok1(tlist_check(&parent.children, NULL));
118                 if (i > 2)
119                         break;
120         }
121         ok1(i == 3);
122         ok1(tlist_empty(&parent.children));
123
124         /* Test list_top/list_tail on empty list. */
125         ok1(tlist_top(&parent.children, struct child, list) == NULL);
126         ok1(tlist_tail(&parent.children, struct child, list) == NULL);
127         return exit_status();
128 }