dbversion_test.c revision 1.3 1 /* $NetBSD: dbversion_test.c,v 1.3 2025/01/26 16:25:47 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 #include <inttypes.h>
17 #include <sched.h> /* IWYU pragma: keep */
18 #include <setjmp.h>
19 #include <stdarg.h>
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #define UNIT_TESTING
26 #include <cmocka.h>
27
28 #include <isc/file.h>
29 #include <isc/result.h>
30 #include <isc/serial.h>
31 #include <isc/stdtime.h>
32 #include <isc/string.h>
33 #include <isc/util.h>
34
35 #include <dns/db.h>
36 #include <dns/nsec3.h>
37 #include <dns/rdatalist.h>
38 #include <dns/rdataset.h>
39 #include <dns/rdatasetiter.h>
40
41 #include <tests/dns.h>
42
43 static char tempname[11] = "dtXXXXXXXX";
44 static dns_db_t *db1 = NULL, *db2 = NULL;
45 static dns_dbversion_t *v1 = NULL, *v2 = NULL;
46
47 /*
48 * The code below enables us to trap assertion failures for testing
49 * purposes. local_callback() is set as the callback function for
50 * isc_assertion_failed(). It calls mock_assert() so that CMOCKA
51 * will be able to see it, then returns to the calling function via
52 * longjmp() so that the abort() call in isc_assertion_failed() will
53 * never be reached. Use check_assertion() to check for assertions
54 * instead of expect_assert_failure().
55 */
56 jmp_buf assertion;
57
58 #define check_assertion(function_call) \
59 do { \
60 const int r = setjmp(assertion); \
61 if (r == 0) { \
62 expect_assert_failure(function_call); \
63 } \
64 } while (false);
65
66 static void
67 local_callback(const char *file, int line, isc_assertiontype_t type,
68 const char *cond) {
69 UNUSED(type);
70
71 mock_assert(1, cond, file, line);
72 longjmp(assertion, 1);
73 }
74
75 static int
76 setup_test(void **state) {
77 isc_result_t res;
78
79 UNUSED(state);
80
81 isc_assertion_setcallback(local_callback);
82
83 res = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname, dns_dbtype_zone,
84 dns_rdataclass_in, 0, NULL, &db1);
85 assert_int_equal(res, ISC_R_SUCCESS);
86 dns_db_newversion(db1, &v1);
87 assert_non_null(v1);
88
89 res = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname, dns_dbtype_zone,
90 dns_rdataclass_in, 0, NULL, &db2);
91 assert_int_equal(res, ISC_R_SUCCESS);
92 dns_db_newversion(db2, &v2);
93 assert_non_null(v1);
94
95 return 0;
96 }
97
98 static int
99 teardown_test(void **state) {
100 UNUSED(state);
101
102 if (strcmp(tempname, "dtXXXXXXXX") != 0) {
103 unlink(tempname);
104 }
105
106 if (v1 != NULL) {
107 dns_db_closeversion(db1, &v1, false);
108 assert_null(v1);
109 }
110 if (db1 != NULL) {
111 dns_db_detach(&db1);
112 assert_null(db1);
113 }
114
115 if (v2 != NULL) {
116 dns_db_closeversion(db2, &v2, false);
117 assert_null(v2);
118 }
119 if (db2 != NULL) {
120 dns_db_detach(&db2);
121 assert_null(db2);
122 }
123
124 return 0;
125 }
126
127 /*
128 * Check dns_db_attachversion() passes with matching db and version, and
129 * asserts with mis-matching db and version.
130 */
131 ISC_RUN_TEST_IMPL(attachversion) {
132 dns_dbversion_t *v = NULL;
133
134 UNUSED(state);
135
136 dns_db_attachversion(db1, v1, &v);
137 assert_ptr_equal(v, v1);
138 dns_db_closeversion(db1, &v, false);
139 assert_null(v);
140
141 check_assertion(dns_db_attachversion(db1, v2, &v));
142 }
143
144 /*
145 * Check dns_db_closeversion() passes with matching db and version, and
146 * asserts with mis-matching db and version.
147 */
148 ISC_RUN_TEST_IMPL(closeversion) {
149 UNUSED(state);
150
151 assert_non_null(v1);
152 dns_db_closeversion(db1, &v1, false);
153 assert_null(v1);
154
155 check_assertion(dns_db_closeversion(db1, &v2, false));
156 }
157
158 /*
159 * Check dns_db_find() passes with matching db and version, and
160 * asserts with mis-matching db and version.
161 */
162 ISC_RUN_TEST_IMPL(find) {
163 isc_result_t res;
164 dns_rdataset_t rdataset;
165 dns_fixedname_t fixed;
166 dns_name_t *name = NULL;
167
168 UNUSED(state);
169
170 name = dns_fixedname_initname(&fixed);
171
172 dns_rdataset_init(&rdataset);
173 res = dns_db_find(db1, dns_rootname, v1, dns_rdatatype_soa, 0, 0, NULL,
174 name, &rdataset, NULL);
175 assert_int_equal(res, DNS_R_NXDOMAIN);
176
177 if (dns_rdataset_isassociated(&rdataset)) {
178 dns_rdataset_disassociate(&rdataset);
179 }
180
181 dns_rdataset_init(&rdataset);
182 check_assertion((void)dns_db_find(db1, dns_rootname, v2,
183 dns_rdatatype_soa, 0, 0, NULL, name,
184 &rdataset, NULL));
185 }
186
187 /*
188 * Check dns_db_allrdatasets() passes with matching db and version, and
189 * asserts with mis-matching db and version.
190 */
191 ISC_RUN_TEST_IMPL(allrdatasets) {
192 isc_result_t res;
193 dns_dbnode_t *node = NULL;
194 dns_rdatasetiter_t *iterator = NULL;
195
196 UNUSED(state);
197
198 res = dns_db_findnode(db1, dns_rootname, false, &node);
199 assert_int_equal(res, ISC_R_SUCCESS);
200
201 res = dns_db_allrdatasets(db1, node, v1, 0, 0, &iterator);
202 assert_int_equal(res, ISC_R_SUCCESS);
203
204 check_assertion(dns_db_allrdatasets(db1, node, v2, 0, 0, &iterator));
205
206 dns_rdatasetiter_destroy(&iterator);
207 assert_null(iterator);
208
209 dns_db_detachnode(db1, &node);
210 assert_null(node);
211 }
212
213 /*
214 * Check dns_db_findrdataset() passes with matching db and version, and
215 * asserts with mis-matching db and version.
216 */
217 ISC_RUN_TEST_IMPL(findrdataset) {
218 isc_result_t res;
219 dns_rdataset_t rdataset;
220 dns_dbnode_t *node = NULL;
221
222 UNUSED(state);
223
224 res = dns_db_findnode(db1, dns_rootname, false, &node);
225 assert_int_equal(res, ISC_R_SUCCESS);
226
227 dns_rdataset_init(&rdataset);
228 res = dns_db_findrdataset(db1, node, v1, dns_rdatatype_soa, 0, 0,
229 &rdataset, NULL);
230 assert_int_equal(res, ISC_R_NOTFOUND);
231
232 if (dns_rdataset_isassociated(&rdataset)) {
233 dns_rdataset_disassociate(&rdataset);
234 }
235
236 dns_rdataset_init(&rdataset);
237 check_assertion(dns_db_findrdataset(db1, node, v2, dns_rdatatype_soa, 0,
238 0, &rdataset, NULL));
239
240 dns_db_detachnode(db1, &node);
241 assert_null(node);
242 }
243
244 /*
245 * Check dns_db_deleterdataset() passes with matching db and version, and
246 * asserts with mis-matching db and version.
247 */
248 ISC_RUN_TEST_IMPL(deleterdataset) {
249 isc_result_t res;
250 dns_dbnode_t *node = NULL;
251
252 UNUSED(state);
253
254 res = dns_db_findnode(db1, dns_rootname, false, &node);
255 assert_int_equal(res, ISC_R_SUCCESS);
256
257 res = dns_db_deleterdataset(db1, node, v1, dns_rdatatype_soa, 0);
258 assert_int_equal(res, DNS_R_UNCHANGED);
259
260 check_assertion(
261 dns_db_deleterdataset(db1, node, v2, dns_rdatatype_soa, 0));
262 dns_db_detachnode(db1, &node);
263 assert_null(node);
264 }
265
266 /*
267 * Check dns_db_subtractrdataset() passes with matching db and version, and
268 * asserts with mis-matching db and version.
269 */
270 ISC_RUN_TEST_IMPL(subtract) {
271 isc_result_t res;
272 dns_rdataset_t rdataset;
273 dns_rdatalist_t rdatalist;
274 dns_dbnode_t *node = NULL;
275
276 UNUSED(state);
277
278 dns_rdataset_init(&rdataset);
279 dns_rdatalist_init(&rdatalist);
280
281 rdatalist.rdclass = dns_rdataclass_in;
282
283 dns_rdatalist_tordataset(&rdatalist, &rdataset);
284
285 res = dns_db_findnode(db1, dns_rootname, false, &node);
286 assert_int_equal(res, ISC_R_SUCCESS);
287
288 res = dns_db_subtractrdataset(db1, node, v1, &rdataset, 0, NULL);
289 assert_int_equal(res, DNS_R_UNCHANGED);
290
291 if (dns_rdataset_isassociated(&rdataset)) {
292 dns_rdataset_disassociate(&rdataset);
293 }
294
295 dns_rdataset_init(&rdataset);
296 dns_rdatalist_tordataset(&rdatalist, &rdataset);
297
298 check_assertion(
299 dns_db_subtractrdataset(db1, node, v2, &rdataset, 0, NULL));
300
301 dns_db_detachnode(db1, &node);
302 assert_null(node);
303 }
304
305 /*
306 * Check dns_db_addrdataset() passes with matching db and version, and
307 * asserts with mis-matching db and version.
308 */
309 ISC_RUN_TEST_IMPL(addrdataset) {
310 isc_result_t res;
311 dns_rdataset_t rdataset;
312 dns_dbnode_t *node = NULL;
313 dns_rdatalist_t rdatalist;
314
315 UNUSED(state);
316
317 dns_rdataset_init(&rdataset);
318 dns_rdatalist_init(&rdatalist);
319
320 rdatalist.rdclass = dns_rdataclass_in;
321
322 dns_rdatalist_tordataset(&rdatalist, &rdataset);
323
324 res = dns_db_findnode(db1, dns_rootname, false, &node);
325 assert_int_equal(res, ISC_R_SUCCESS);
326
327 res = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, NULL);
328 assert_int_equal(res, ISC_R_SUCCESS);
329
330 check_assertion(
331 dns_db_addrdataset(db1, node, v2, 0, &rdataset, 0, NULL));
332
333 dns_db_detachnode(db1, &node);
334 assert_null(node);
335 }
336
337 /*
338 * Check dns_db_getnsec3parameters() passes with matching db and version,
339 * and asserts with mis-matching db and version.
340 */
341 ISC_RUN_TEST_IMPL(getnsec3parameters) {
342 isc_result_t res;
343 dns_hash_t hash;
344 uint8_t flags;
345 uint16_t iterations;
346 unsigned char salt[DNS_NSEC3_SALTSIZE];
347 size_t salt_length = sizeof(salt);
348
349 UNUSED(state);
350
351 res = dns_db_getnsec3parameters(db1, v1, &hash, &flags, &iterations,
352 salt, &salt_length);
353 assert_int_equal(res, ISC_R_NOTFOUND);
354
355 check_assertion(dns_db_getnsec3parameters(
356 db1, v2, &hash, &flags, &iterations, salt, &salt_length));
357 }
358
359 ISC_TEST_LIST_START
360 ISC_TEST_ENTRY_CUSTOM(find, setup_test, teardown_test)
361 ISC_TEST_ENTRY_CUSTOM(allrdatasets, setup_test, teardown_test)
362 ISC_TEST_ENTRY_CUSTOM(findrdataset, setup_test, teardown_test)
363 ISC_TEST_ENTRY_CUSTOM(deleterdataset, setup_test, teardown_test)
364 ISC_TEST_ENTRY_CUSTOM(subtract, setup_test, teardown_test)
365 ISC_TEST_ENTRY_CUSTOM(addrdataset, setup_test, teardown_test)
366 ISC_TEST_ENTRY_CUSTOM(getnsec3parameters, setup_test, teardown_test)
367 ISC_TEST_ENTRY_CUSTOM(attachversion, setup_test, teardown_test)
368 ISC_TEST_ENTRY_CUSTOM(closeversion, setup_test, teardown_test)
369 ISC_TEST_LIST_END
370
371 ISC_TEST_MAIN
372