take: new module for parameter ownership.
[ccan] / ccan / take / test / run.c
1 #include <stdlib.h>
2 #include <stdbool.h>
3
4 static bool fail_realloc;
5 static void *my_realloc(void *p, size_t len)
6 {
7         if (fail_realloc)
8                 return NULL;
9         return realloc(p, len);
10 }
11 #define realloc my_realloc
12
13 #include <ccan/take/take.h>
14 #include <ccan/take/take.c>
15 #include <ccan/tap/tap.h>
16
17 static int my_allocfail_called;
18 static void my_allocfail(const void *p)
19 {
20         my_allocfail_called++;
21 }       
22
23 static void recurse(const char *takeme, int count)
24 {
25         if (count < 1000)
26                 recurse(take(strdup(takeme)), count+1);
27         if (taken(takeme))
28                 free((char *)takeme);
29 }
30
31 int main(void)
32 {
33         const char *p = "hi";
34
35         plan_tests(43);
36
37         /* We can take NULL. */
38         ok1(take(NULL) == NULL);
39         ok1(is_taken(NULL));
40         ok1(taken_any());
41         ok1(taken(NULL)); /* Undoes take() */
42         ok1(!is_taken(NULL));
43         ok1(!taken(NULL));
44
45         /* We can take NULL twice! */
46         ok1(take(NULL) == NULL);
47         ok1(take(NULL) == NULL);
48         ok1(is_taken(NULL));
49         ok1(taken_any());
50         ok1(taken(NULL)); /* Undoes take() */
51         ok1(is_taken(NULL));
52         ok1(taken_any());
53         ok1(taken(NULL)); /* Undoes take() */
54         ok1(!is_taken(NULL));
55         ok1(!taken(NULL));
56         ok1(!taken_any());
57
58         /* We can take a real pointer. */
59         ok1(take(p) == p);
60         ok1(is_taken(p));
61         ok1(taken_any());
62         ok1(taken(p)); /* Undoes take() */
63         ok1(!is_taken(p));
64         ok1(!taken(p));
65         ok1(!taken_any());
66
67         /* Force a failure. */
68         ok1(!my_allocfail_called);
69         ok1(take(p) == p);
70         ok1(take(p+1) == p+1);
71
72         fail_realloc = true;
73         /* Without a handler, must pass through and leak. */
74         ok1(take(p+2) == p+2);
75         ok1(!taken(p+2));
76
77         /* Now, with a handler. */
78         take_allocfail(my_allocfail);
79         ok1(take(p+2) == NULL);
80
81         ok1(my_allocfail_called == 1);
82         ok1(taken_any());
83         ok1(taken(p));
84         ok1(taken(p+1));
85         ok1(is_taken(NULL));
86         ok1(taken(NULL));
87         ok1(!taken(NULL));
88         ok1(!taken_any());
89
90         /* Test some deep nesting. */
91         fail_realloc = false;
92         recurse("hello", 0);
93         ok1(max_taken == 1000);
94         ok1(!taken_any());
95
96         take_cleanup();
97         ok1(num_taken == 0);
98         ok1(max_taken == 0);
99         ok1(takenarr == NULL);
100
101         return exit_status();
102 }