]> git.ozlabs.org Git - ccan/blob - ccan/tlist2/test/run_2.c
tlist2: a alternate to tlist that encodes the member offset into the container type
[ccan] / ccan / tlist2 / test / run_2.c
1 #define CCAN_LIST_DEBUG 1
2 #include <ccan/tlist2/tlist2.h>
3 #include <ccan/tap/tap.h>
4
5 struct child {
6         const char *name;
7         struct list_node list;
8 };
9
10 struct parent {
11         const char *name;
12         TLIST2(struct child, list) children;
13         unsigned int num_children;
14 };
15
16 int main(int argc, char *argv[])
17 {
18         struct parent parent;
19         struct child c1, c2, c3, *c, *n;
20         unsigned int i;
21         TLIST2(struct child, list) tlist = TLIST2_INIT(tlist);
22
23         plan_tests(48);
24         /* Test TLIST2_INIT, and tlist2_empty */
25         ok1(tlist2_empty(&tlist));
26         ok1(tlist2_check(&tlist, NULL));
27
28         parent.num_children = 0;
29         tlist2_init(&parent.children);
30         /* Test tlist2_init */
31         ok1(tlist2_empty(&parent.children));
32         ok1(tlist2_check(&parent.children, NULL));
33
34         c2.name = "c2";
35         tlist2_add(&parent.children, &c2);
36         /* Test tlist2_add and !tlist2_empty. */
37         ok1(!tlist2_empty(&parent.children));
38         ok1(c2.list.next == &tlist2_unwrap(&parent.children)->n);
39         ok1(c2.list.prev == &tlist2_unwrap(&parent.children)->n);
40         ok1(tlist2_unwrap(&parent.children)->n.next == &c2.list);
41         ok1(tlist2_unwrap(&parent.children)->n.prev == &c2.list);
42         /* Test tlist2_check */
43         ok1(tlist2_check(&parent.children, NULL));
44
45         c1.name = "c1";
46         tlist2_add(&parent.children, &c1);
47         /* Test list_add and !list_empty. */
48         ok1(!tlist2_empty(&parent.children));
49         ok1(c2.list.next == &tlist2_unwrap(&parent.children)->n);
50         ok1(c2.list.prev == &c1.list);
51         ok1(tlist2_unwrap(&parent.children)->n.next == &c1.list);
52         ok1(tlist2_unwrap(&parent.children)->n.prev == &c2.list);
53         ok1(c1.list.next == &c2.list);
54         ok1(c1.list.prev == &tlist2_unwrap(&parent.children)->n);
55         /* Test tlist2_check */
56         ok1(tlist2_check(&parent.children, NULL));
57
58         c3.name = "c3";
59         tlist2_add_tail(&parent.children, &c3);
60         /* Test list_add_tail and !list_empty. */
61         ok1(!tlist2_empty(&parent.children));
62         ok1(tlist2_unwrap(&parent.children)->n.next == &c1.list);
63         ok1(tlist2_unwrap(&parent.children)->n.prev == &c3.list);
64         ok1(c1.list.next == &c2.list);
65         ok1(c1.list.prev == &tlist2_unwrap(&parent.children)->n);
66         ok1(c2.list.next == &c3.list);
67         ok1(c2.list.prev == &c1.list);
68         ok1(c3.list.next == &tlist2_unwrap(&parent.children)->n);
69         ok1(c3.list.prev == &c2.list);
70         /* Test tlist2_check */
71         ok1(tlist2_check(&parent.children, NULL));
72
73         /* Test tlist2_top */
74         ok1(tlist2_top(&parent.children) == &c1);
75
76         /* Test list_tail */
77         ok1(tlist2_tail(&parent.children) == &c3);
78
79         /* Test tlist2_for_each. */
80         i = 0;
81         tlist2_for_each(&parent.children, c) {
82                 switch (i++) {
83                 case 0:
84                         ok1(c == &c1);
85                         break;
86                 case 1:
87                         ok1(c == &c2);
88                         break;
89                 case 2:
90                         ok1(c == &c3);
91                         break;
92                 }
93                 if (i > 2)
94                         break;
95         }
96         ok1(i == 3);
97
98         /* Test tlist2_for_each_rev. */
99         i = 0;
100         tlist2_for_each_rev(&parent.children, c) {
101                 switch (i++) {
102                 case 0:
103                         ok1(c == &c3);
104                         break;
105                 case 1:
106                         ok1(c == &c2);
107                         break;
108                 case 2:
109                         ok1(c == &c1);
110                         break;
111                 }
112                 if (i > 2)
113                         break;
114         }
115         ok1(i == 3);
116
117         /* Test tlist2_for_each_safe, tlist2_del and tlist2_del_from. */
118         i = 0;
119         tlist2_for_each_safe(&parent.children, c, n) {
120                 switch (i++) {
121                 case 0:
122                         ok1(c == &c1);
123                         tlist2_del_from(&parent.children, c);
124                         break;
125                 case 1:
126                         ok1(c == &c2);
127                         tlist2_del_from(&parent.children, c);
128                         break;
129                 case 2:
130                         ok1(c == &c3);
131                         tlist2_del_from(&parent.children, c);
132                         break;
133                 }
134                 ok1(tlist2_check(&parent.children, NULL));
135                 if (i > 2)
136                         break;
137         }
138         ok1(i == 3);
139         ok1(tlist2_empty(&parent.children));
140
141         /* Test list_top/list_tail on empty list. */
142         ok1(tlist2_top(&parent.children) == (struct child *)NULL);
143         ok1(tlist2_tail(&parent.children) == (struct child *)NULL);
144         return exit_status();
145 }