tal: add general notifiers.
[ccan] / ccan / tal / test / run-notifier.c
1 #include <ccan/tal/tal.h>
2 #include <ccan/tal/tal.c>
3 #include <ccan/tap/tap.h>
4
5 static enum tal_notify_type expect;
6 static void *expect_info;
7 static char *ctx;
8 static unsigned int notified1, notified2;
9
10 /* Make sure we always move on resize. */
11 static void *my_realloc(void *old, size_t size)
12 {
13         void *new = realloc(old, size);
14         if (new == old) {
15                 void *p = malloc(size);
16                 memcpy(p, old, size);
17                 free(old);
18                 new = p;
19         }
20         return new;
21 }
22
23 static void notify1(char *p, enum tal_notify_type notify, void *info)
24 {
25         ok1(ctx == ctx);
26         ok1(notify == expect);
27         if (expect_info == &expect_info)
28                 expect_info = info;
29         else
30                 ok1(info == expect_info);
31         notified1++;
32 }
33
34 static void notify2(char *ctx, enum tal_notify_type notify, void *info)
35 {
36         notified2++;
37 }
38
39 static bool seen_move, seen_resize;
40 static void resize_notifier(char *p, enum tal_notify_type notify, void *info)
41 {
42         if (notify == TAL_NOTIFY_MOVE) {
43                 ok1(!seen_move);
44                 ok1(!seen_resize);
45                 ok1(info == ctx);
46                 ok1(p != ctx);
47                 ctx = p;
48                 seen_move = true;
49         } else if (notify == TAL_NOTIFY_RESIZE) {
50                 ok1(!seen_resize);
51                 ok1(seen_move);
52                 ok1(p == ctx);
53                 ok1((size_t)info == 100);
54                 seen_resize = true;
55         } else
56                 fail("Unexpected notifier %i", notify);
57 }
58
59 int main(void)
60 {
61         char *child, *new_ctx;
62
63         plan_tests(56);
64
65         ctx = tal(NULL, char);
66         ok1(tal_add_notifier(ctx, 511, notify1));
67         ok1(notified1 == 0);
68         ok1(notified2 == 0);
69
70         expect = TAL_NOTIFY_STEAL;
71         expect_info = NULL;
72         ok1(tal_steal(NULL, ctx) == ctx);
73         ok1(notified1 == 1);
74
75         expect = TAL_NOTIFY_ADD_NOTIFIER;
76         expect_info = notify2;
77         ok1(tal_add_notifier(ctx, TAL_NOTIFY_RENAME|TAL_NOTIFY_ADD_NOTIFIER
78                              |TAL_NOTIFY_DEL_NOTIFIER, notify2));
79         ok1(notified1 == 2);
80         ok1(notified2 == 0);
81
82         expect = TAL_NOTIFY_RENAME;
83         expect_info = (char *)"newname";
84         ok1(tal_set_name(ctx, (char *)expect_info));
85         ok1(notified1 == 3);
86         ok1(notified2 == 1);
87
88         expect = TAL_NOTIFY_DEL_NOTIFIER;
89         expect_info = notify2;
90         ok1(tal_del_notifier(ctx, notify2));
91         ok1(notified1 == 4);
92         ok1(notified2 == 1);
93
94         /* Failed delete should not call notifier! */
95         expect = TAL_NOTIFY_DEL_NOTIFIER;
96         expect_info = notify2;
97         ok1(!tal_del_notifier(ctx, notify2));
98         ok1(notified1 == 4);
99         ok1(notified2 == 1);
100
101         expect = TAL_NOTIFY_ADD_CHILD;
102         expect_info = &expect_info;
103         child = tal(ctx, char);
104         ok1(notified1 == 5);
105         ok1(notified2 == 1);
106         ok1(expect_info == child);
107
108         expect = TAL_NOTIFY_DEL_CHILD;
109         expect_info = child;
110         tal_free(child);
111         ok1(notified1 == 6);
112         ok1(notified2 == 1);
113
114         expect = TAL_NOTIFY_FREE;
115         expect_info = ctx;
116         tal_free(ctx);
117         ok1(notified1 == 7);
118         ok1(notified2 == 1);
119
120         tal_set_backend(NULL, my_realloc, NULL, NULL);
121         ctx = new_ctx = tal(NULL, char);
122         ok1(tal_add_notifier(new_ctx, 511, resize_notifier));
123         ok1(tal_resize(&new_ctx, 100));
124         ok1(seen_move);
125         ok1(seen_resize);
126         tal_del_notifier(new_ctx, resize_notifier);
127         tal_free(new_ctx);
128
129         return exit_status();
130 }