Fix missing va_end()s
[ccan] / ccan / ntdb / test / run-capabilities.c
1 #include <ccan/failtest/failtest_override.h>
2 #include "ntdb-source.h"
3 #include "tap-interface.h"
4 #include "logging.h"
5 #include "layout.h"
6 #include "failtest_helper.h"
7 #include <stdarg.h>
8 #include "helprun-external-agent.h"
9
10 static size_t len_of(bool breaks_check, bool breaks_write, bool breaks_open)
11 {
12         size_t len = 0;
13         if (breaks_check)
14                 len += 8;
15         if (breaks_write)
16                 len += 16;
17         if (breaks_open)
18                 len += 32;
19         return len;
20 }
21
22 /* Creates a NTDB with various capabilities. */
23 static void create_ntdb(const char *name,
24                        unsigned int cap,
25                        bool breaks_check,
26                        bool breaks_write,
27                        bool breaks_open, ...)
28 {
29         NTDB_DATA key, data;
30         va_list ap;
31         struct ntdb_layout *layout;
32         struct ntdb_context *ntdb;
33         int fd, clen;
34         union ntdb_attribute seed_attr;
35
36         /* Force a seed which doesn't allow records to clash! */
37         seed_attr.base.attr = NTDB_ATTRIBUTE_SEED;
38         seed_attr.base.next = &tap_log_attr;
39         seed_attr.seed.seed = 0;
40
41         key = ntdb_mkdata("Hello", 5);
42         data = ntdb_mkdata("world", 5);
43
44         /* Create a NTDB with some data, and some capabilities */
45         layout = new_ntdb_layout();
46         ntdb_layout_add_freetable(layout);
47         ntdb_layout_add_used(layout, key, data, 6);
48         clen = len_of(breaks_check, breaks_write, breaks_open);
49         ntdb_layout_add_free(layout, 15496 - clen, 0);
50         ntdb_layout_add_capability(layout, cap,
51                                    breaks_write, breaks_check, breaks_open,
52                                    clen);
53
54         va_start(ap, breaks_open);
55         while ((cap = va_arg(ap, int)) != 0) {
56                 breaks_check = va_arg(ap, int);
57                 breaks_write = va_arg(ap, int);
58                 breaks_open = va_arg(ap, int);
59
60                 key.dsize--;
61                 ntdb_layout_add_used(layout, key, data, 11 - key.dsize);
62                 clen = len_of(breaks_check, breaks_write, breaks_open);
63                 ntdb_layout_add_free(layout, 16304 - clen, 0);
64                 ntdb_layout_add_capability(layout, cap,
65                                           breaks_write, breaks_check,
66                                           breaks_open, clen);
67         }
68         va_end(ap);
69
70         /* We open-code this, because we need to use the failtest write. */
71         ntdb = ntdb_layout_get(layout, failtest_free, &seed_attr);
72
73         fd = open(name, O_RDWR|O_TRUNC|O_CREAT, 0600);
74         if (fd < 0)
75                 err(1, "opening %s for writing", name);
76         if (write(fd, ntdb->file->map_ptr, ntdb->file->map_size)
77             != ntdb->file->map_size)
78                 err(1, "writing %s", name);
79         close(fd);
80         ntdb_close(ntdb);
81         ntdb_layout_free(layout);
82 }
83
84 /* Note all the "goto out" early exits: they're to shorten failtest time. */
85 int main(int argc, char *argv[])
86 {
87         struct ntdb_context *ntdb;
88         char *summary;
89
90         failtest_init(argc, argv);
91         failtest_hook = block_repeat_failures;
92         failtest_exit_check = exit_check_log;
93         plan_tests(60);
94
95         failtest_suppress = true;
96         /* Capability says you can ignore it? */
97         create_ntdb("run-capabilities.ntdb", 1, false, false, false, 0);
98
99         failtest_suppress = false;
100         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
101                          &tap_log_attr);
102         failtest_suppress = true;
103         if (!ok1(ntdb))
104                 goto out;
105         ok1(tap_log_messages == 0);
106         ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
107         ok1(tap_log_messages == 0);
108         ntdb_close(ntdb);
109
110         /* Two capabilitues say you can ignore them? */
111         create_ntdb("run-capabilities.ntdb",
112                    1, false, false, false,
113                    2, false, false, false, 0);
114
115         failtest_suppress = false;
116         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
117                          &tap_log_attr);
118         failtest_suppress = true;
119         if (!ok1(ntdb))
120                 goto out;
121         ok1(tap_log_messages == 0);
122         ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
123         ok1(tap_log_messages == 0);
124         ok1(ntdb_summary(ntdb, 0, &summary) == NTDB_SUCCESS);
125         ok1(strstr(summary, "Capability 1\n"));
126         free(summary);
127         ntdb_close(ntdb);
128
129         /* Capability says you can't check. */
130         create_ntdb("run-capabilities.ntdb",
131                    1, false, false, false,
132                    2, true, false, false, 0);
133
134         failtest_suppress = false;
135         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
136                          &tap_log_attr);
137         failtest_suppress = true;
138         if (!ok1(ntdb))
139                 goto out;
140         ok1(tap_log_messages == 0);
141         ok1(ntdb_get_flags(ntdb) & NTDB_CANT_CHECK);
142         ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
143         /* We expect a warning! */
144         ok1(tap_log_messages == 1);
145         ok1(strstr(log_last, "capabilit"));
146         ok1(ntdb_summary(ntdb, 0, &summary) == NTDB_SUCCESS);
147         ok1(strstr(summary, "Capability 1\n"));
148         ok1(strstr(summary, "Capability 2 (uncheckable)\n"));
149         free(summary);
150         ntdb_close(ntdb);
151
152         /* Capability says you can't write. */
153         create_ntdb("run-capabilities.ntdb",
154                    1, false, false, false,
155                    2, false, true, false, 0);
156
157         failtest_suppress = false;
158         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
159                          &tap_log_attr);
160         failtest_suppress = true;
161         /* We expect a message. */
162         ok1(!ntdb);
163         if (!ok1(tap_log_messages == 2))
164                 goto out;
165         if (!ok1(strstr(log_last, "unknown")))
166                 goto out;
167         ok1(strstr(log_last, "write"));
168
169         /* We can open it read-only though! */
170         failtest_suppress = false;
171         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDONLY, 0,
172                          &tap_log_attr);
173         failtest_suppress = true;
174         if (!ok1(ntdb))
175                 goto out;
176         ok1(tap_log_messages == 2);
177         ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
178         ok1(tap_log_messages == 2);
179         ok1(ntdb_summary(ntdb, 0, &summary) == NTDB_SUCCESS);
180         ok1(strstr(summary, "Capability 1\n"));
181         ok1(strstr(summary, "Capability 2 (read-only)\n"));
182         free(summary);
183         ntdb_close(ntdb);
184
185         /* Capability says you can't open. */
186         create_ntdb("run-capabilities.ntdb",
187                    1, false, false, false,
188                    2, false, false, true, 0);
189
190         failtest_suppress = false;
191         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
192                        &tap_log_attr);
193         failtest_suppress = true;
194         /* We expect a message. */
195         ok1(!ntdb);
196         if (!ok1(tap_log_messages == 3))
197                 goto out;
198         if (!ok1(strstr(log_last, "unknown")))
199                 goto out;
200
201         /* Combine capabilities correctly. */
202         create_ntdb("run-capabilities.ntdb",
203                    1, false, false, false,
204                    2, true, false, false,
205                    3, false, true, false, 0);
206
207         failtest_suppress = false;
208         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
209                        &tap_log_attr);
210         failtest_suppress = true;
211         /* We expect a message. */
212         ok1(!ntdb);
213         if (!ok1(tap_log_messages == 4))
214                 goto out;
215         if (!ok1(strstr(log_last, "unknown")))
216                 goto out;
217         ok1(strstr(log_last, "write"));
218
219         /* We can open it read-only though! */
220         failtest_suppress = false;
221         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDONLY, 0,
222                        &tap_log_attr);
223         failtest_suppress = true;
224         if (!ok1(ntdb))
225                 goto out;
226         ok1(tap_log_messages == 4);
227         ok1(ntdb_get_flags(ntdb) & NTDB_CANT_CHECK);
228         ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
229         /* We expect a warning! */
230         ok1(tap_log_messages == 5);
231         ok1(strstr(log_last, "unknown"));
232         ok1(ntdb_summary(ntdb, 0, &summary) == NTDB_SUCCESS);
233         ok1(strstr(summary, "Capability 1\n"));
234         ok1(strstr(summary, "Capability 2 (uncheckable)\n"));
235         ok1(strstr(summary, "Capability 3 (read-only)\n"));
236         free(summary);
237         ntdb_close(ntdb);
238
239         /* Two capability flags in one. */
240         create_ntdb("run-capabilities.ntdb",
241                    1, false, false, false,
242                    2, true, true, false,
243                    0);
244
245         failtest_suppress = false;
246         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDWR, 0,
247                        &tap_log_attr);
248         failtest_suppress = true;
249         /* We expect a message. */
250         ok1(!ntdb);
251         if (!ok1(tap_log_messages == 6))
252                 goto out;
253         if (!ok1(strstr(log_last, "unknown")))
254                 goto out;
255         ok1(strstr(log_last, "write"));
256
257         /* We can open it read-only though! */
258         failtest_suppress = false;
259         ntdb = ntdb_open("run-capabilities.ntdb", MAYBE_NOSYNC, O_RDONLY, 0,
260                        &tap_log_attr);
261         failtest_suppress = true;
262         if (!ok1(ntdb))
263                 goto out;
264         ok1(tap_log_messages == 6);
265         ok1(ntdb_get_flags(ntdb) & NTDB_CANT_CHECK);
266         ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
267         /* We expect a warning! */
268         ok1(tap_log_messages == 7);
269         ok1(strstr(log_last, "unknown"));
270         ok1(ntdb_summary(ntdb, 0, &summary) == NTDB_SUCCESS);
271         ok1(strstr(summary, "Capability 1\n"));
272         ok1(strstr(summary, "Capability 2 (uncheckable,read-only)\n"));
273         free(summary);
274         ntdb_close(ntdb);
275
276 out:
277         failtest_exit(exit_status());
278
279         /*
280          * We will never reach this but the compiler complains if we do not
281          * return in this function.
282          */
283         return EFAULT;
284 }