]> git.ozlabs.org Git - ccan/blob - ccan/rbtree/test/run-many.c
rbtree: use failtest to check handling of allocation failures.
[ccan] / ccan / rbtree / test / run-many.c
1 #include <ccan/rbtree/rbtree.c>
2 #include <ccan/tap/tap.h>
3 #include <ccan/talloc/talloc.h>
4 #include <string.h>
5 #include <stdbool.h>
6 #include <ccan/failtest/failtest_override.h>
7 #include <ccan/failtest/failtest.h>
8 #define NUM_ELEMS 100
9
10 /* We want to test talloc failure paths. */
11 static void *my_malloc(size_t size)
12 {
13         return malloc(size);
14 }
15
16 static void my_free(void *ptr)
17 {
18         free(ptr);
19 }
20
21 static void *my_realloc(void *ptr, size_t size)
22 {
23         return realloc(ptr, size);
24 }
25
26 static bool lookup_all(trbt_tree_t *rb, bool exist)
27 {
28         unsigned int i;
29
30         for (i = 0; i < NUM_ELEMS; i++) {
31                 int *p = trbt_lookup32(rb, i);
32                 if (p) {
33                         if (!exist)
34                                 return false;
35                         if (*p != i)
36                                 return false;
37                 } else
38                         if (exist)
39                                 return false;
40         }
41         return true;
42 }
43
44 static bool add_one(trbt_tree_t *rb, bool exist, unsigned int i)
45 {
46         int *new = talloc_memdup(rb, &i, sizeof(i));
47         int *p;
48
49         if (!new)
50                 return false;
51
52         p = trbt_insert32(rb, i, new);
53         if (p) {
54                 if (!exist)
55                         return false;
56                 if (*p != i)
57                         return false;
58         } else {
59                 if (exist)
60                         return false;
61                 else
62                         if (!trbt_lookup32(rb, i))
63                                 return false;
64         }
65         return true;
66 }
67
68 static bool insert_all(trbt_tree_t *rb, bool exist)
69 {
70         unsigned int i;
71
72         for (i = 0; i < NUM_ELEMS; i++) {
73                 if (!add_one(rb, exist, i))
74                         return false;
75         }
76         return true;
77 }
78
79 static void delete_all(trbt_tree_t *rb)
80 {
81         unsigned int i;
82
83         /* Don't delete them in the obvious order. */
84         for (i = 0; i < NUM_ELEMS / 2; i++) {
85                 trbt_delete32(rb, i);
86         }
87
88         for (i = NUM_ELEMS-1; i >= NUM_ELEMS / 2; i--) {
89                 trbt_delete32(rb, i);
90         }
91 }
92
93 static void *ctx;
94 static trbt_tree_t *rb;
95
96 static void exit_test(void)
97 {
98         talloc_free(rb);
99         ok1(talloc_total_blocks(ctx) == 1);
100         talloc_free(ctx);
101         failtest_exit(exit_status());
102 }
103
104 int main(int argc, char *argv[])
105 {
106         failtest_init(argc, argv);
107         tap_fail_callback = exit_test;
108         plan_tests(8);
109
110         ctx = talloc_strdup(NULL, "toplevel");
111
112         talloc_set_allocator(my_malloc, my_free, my_realloc);
113
114         rb = trbt_create(ctx, 0);
115         ok1(rb);
116
117         /* None should be there. */
118         ok1(lookup_all(rb, false));
119
120         /* Insert, none should be there previously. */
121         ok1(insert_all(rb, false));
122
123         /* All there now. */
124         ok1(lookup_all(rb, true));
125
126         /* Replace all. */
127         ok1(insert_all(rb, true));
128
129         /* Delete all. */
130         delete_all(rb);
131
132         /* One more time... */
133         ok1(lookup_all(rb, false));
134         ok1(insert_all(rb, false));
135
136         /* All are children of rb, so this is clean. */
137         talloc_free(rb);
138
139         /* No memory leaks? */
140         ok1(talloc_total_blocks(ctx) == 1);
141         talloc_free(ctx);
142
143         /* This exits depending on whether all tests passed */
144         failtest_exit(exit_status());
145 }