Home | History | Annotate | Line # | Download | only in dns
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