compiler: RETURNS_NONNULL macro
[ccan] / ccan / rbtree / test / run.c
1 #include <ccan/failtest/failtest.h>
2 #include <ccan/rbtree/rbtree.c>
3 #include <ccan/tap/tap.h>
4 #include <ccan/talloc/talloc.h>
5 #include <string.h>
6
7 /* We want to test talloc failure paths. */
8 static void *my_malloc(size_t size)
9 {
10         return malloc(size);
11 }
12
13 static void my_free(void *ptr)
14 {
15         free(ptr);
16 }
17
18 static void *my_realloc(void *ptr, size_t size)
19 {
20         return realloc(ptr, size);
21 }
22
23 static void *insert_callback(void *param, void *data)
24 {
25         ok1(data == param);
26         return talloc_strdup(NULL, "insert_callback");
27 }
28
29 int main(void)
30 {
31         trbt_tree_t *rb;
32         void *ctx = talloc_strdup(NULL, "toplevel");
33         char *data, *data2;
34
35         /* This is how many tests you plan to run */
36         plan_tests(19);
37
38         talloc_set_allocator(my_malloc, my_free, my_realloc);
39
40         rb = trbt_create(ctx, 0);
41         ok1(rb);
42         ok1(talloc_is_parent(rb, ctx));
43
44         /* Failed lookup. */
45         ok1(trbt_lookup32(rb, 0) == NULL);
46         ok1(trbt_lookup32(rb, -1) == NULL);
47
48         /* Insert, should steal node onto data. */
49         data = talloc_strdup(NULL, "data");
50         ok1(trbt_insert32(rb, 0, data) == NULL);
51         ok1(trbt_lookup32(rb, 0) == data);
52         ok1(trbt_lookup32(rb, -1) == NULL);
53
54         /* Thus, freeing the data will delete the node. */
55         talloc_free(data);
56         ok1(trbt_lookup32(rb, 0) == NULL);
57
58         /* Try again. */
59         data = talloc_strdup(NULL, "data");
60         ok1(trbt_insert32(rb, 0, data) == NULL);
61
62         /* Another insert should return old one. */
63         data2 = talloc_strdup(NULL, "data2");
64         ok1(trbt_insert32(rb, 0, data2) == data);
65         ok1(trbt_lookup32(rb, 0) == data2);
66
67         /* Freeing old data has no effect. */
68         talloc_free(data);
69         ok1(trbt_lookup32(rb, 0) == data2);
70
71         /* Insert with callback on non-existing. */
72         trbt_insert32_callback(rb, 1, insert_callback, NULL);
73         ok1(strcmp(trbt_lookup32(rb, 1), "insert_callback") == 0);
74         /* Insert with callback on existing. */
75         trbt_insert32_callback(rb, 0, insert_callback, data2);
76         ok1(strcmp(trbt_lookup32(rb, 0), "insert_callback") == 0);
77         talloc_free(data2);
78
79         /* Delete. */
80         data2 = trbt_lookup32(rb, 1);
81         trbt_delete32(rb, 1);
82         ok1(trbt_lookup32(rb, 1) == NULL);
83         ok1(trbt_lookup32(rb, 0));
84         talloc_free(data2);
85
86         /* This should free everything. */
87         talloc_free(trbt_lookup32(rb, 0));
88         talloc_free(rb);
89
90         /* No memory leaks? */
91         ok1(talloc_total_blocks(ctx) == 1);
92         talloc_free(ctx);
93
94         /* This exits depending on whether all tests passed */
95         failtest_exit(exit_status());
96 }