typesafe_cb: simplify, preserve namespace.
[ccan] / ccan / talloc_link / test / run.c
1 #include <ccan/talloc_link/talloc_link.h>
2 #include <ccan/tap/tap.h>
3 #include <ccan/talloc_link/talloc_link.c>
4 #include <stdlib.h>
5 #include <err.h>
6
7 static unsigned int destroy_count = 0;
8 static int destroy_obj(void *obj)
9 {
10         destroy_count++;
11         return 0;
12 }
13
14 int main(int argc, char *argv[])
15 {
16         void *obj, *p1, *p2, *p3;
17
18         plan_tests(16);
19
20         talloc_enable_leak_report();
21
22         /* Single parent case. */
23         p1 = talloc(NULL, char);
24         obj = talloc_linked(p1, talloc(NULL, char));
25         talloc_set_destructor(obj, destroy_obj);
26
27         ok(destroy_count == 0, "destroy_count = %u", destroy_count);
28         talloc_free(p1);
29         ok(destroy_count == 1, "destroy_count = %u", destroy_count);
30
31         /* Dual parent case. */
32         p1 = talloc(NULL, char);
33         obj = talloc_linked(p1, talloc(NULL, char));
34         talloc_set_destructor(obj, destroy_obj);
35         p2 = talloc(NULL, char);
36         talloc_link(p2, obj);
37
38         talloc_free(p1);
39         ok(destroy_count == 1, "destroy_count = %u", destroy_count);
40         talloc_free(p2);
41         ok(destroy_count == 2, "destroy_count = %u", destroy_count);
42         
43         /* Triple parent case. */
44         p1 = talloc(NULL, char);
45         obj = talloc_linked(p1, talloc(NULL, char));
46         talloc_set_destructor(obj, destroy_obj);
47
48         p2 = talloc(NULL, char);
49         p3 = talloc(NULL, char);
50
51         talloc_link(p2, obj);
52         talloc_link(p3, obj);
53
54         talloc_free(p1);
55         ok(destroy_count == 2, "destroy_count = %u", destroy_count);
56         talloc_free(p2);
57         ok(destroy_count == 2, "destroy_count = %u", destroy_count);
58         talloc_free(p3);
59         ok(destroy_count == 3, "destroy_count = %u", destroy_count);
60
61         /* Single delink case. */
62         p1 = talloc(NULL, char);
63         obj = talloc_linked(p1, talloc(NULL, char));
64         talloc_set_destructor(obj, destroy_obj);
65
66         ok(destroy_count == 3, "destroy_count = %u", destroy_count);
67         talloc_delink(p1, obj);
68         ok(destroy_count == 4, "destroy_count = %u", destroy_count);
69         talloc_free(p1);
70
71         /* Double delink case. */
72         p1 = talloc(NULL, char);
73         obj = talloc_linked(p1, talloc(NULL, char));
74         talloc_set_destructor(obj, destroy_obj);
75
76         p2 = talloc(NULL, char);
77         talloc_link(p2, obj);
78
79         talloc_delink(p1, obj);
80         ok(destroy_count == 4, "destroy_count = %u", destroy_count);
81         talloc_delink(p2, obj);
82         ok(destroy_count == 5, "destroy_count = %u", destroy_count);
83         talloc_free(p1);
84         talloc_free(p2);
85
86         /* Delink and free. */
87         p1 = talloc(NULL, char);
88         obj = talloc_linked(p1, talloc(NULL, char));
89         talloc_set_destructor(obj, destroy_obj);
90         p2 = talloc(NULL, char);
91         talloc_link(p2, obj);
92
93         talloc_delink(p1, obj);
94         ok(destroy_count == 5, "destroy_count = %u", destroy_count);
95         talloc_free(p2);
96         ok(destroy_count == 6, "destroy_count = %u", destroy_count);
97         talloc_free(p1);
98
99         /* Free and delink. */
100         p1 = talloc(NULL, char);
101         obj = talloc_linked(p1, talloc(NULL, char));
102         talloc_set_destructor(obj, destroy_obj);
103         p2 = talloc(NULL, char);
104         talloc_link(p2, obj);
105
106         talloc_free(p1);
107         ok(destroy_count == 6, "destroy_count = %u", destroy_count);
108         talloc_delink(p2, obj);
109         ok(destroy_count == 7, "destroy_count = %u", destroy_count);
110         talloc_free(p2);
111
112         /* No leaks? */
113         ok1(talloc_total_size(NULL) == 0);
114
115         return exit_status();
116 }