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