Home | History | Annotate | Line # | Download | only in dns
db_test.c revision 1.2.2.2
      1 /*	$NetBSD: db_test.c,v 1.2.2.2 2024/02/25 15:47:39 martin 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 <unistd.h>
     23 
     24 #define UNIT_TESTING
     25 #include <cmocka.h>
     26 
     27 #include <dns/db.h>
     28 #include <dns/dbiterator.h>
     29 #include <dns/journal.h>
     30 #include <dns/name.h>
     31 #include <dns/rdatalist.h>
     32 
     33 #include <tests/dns.h>
     34 
     35 #define BUFLEN	    255
     36 #define BIGBUFLEN   (64 * 1024)
     37 #define TEST_ORIGIN "test"
     38 
     39 /*
     40  * Individual unit tests
     41  */
     42 
     43 /* test multiple calls to dns_db_getoriginnode */
     44 ISC_RUN_TEST_IMPL(getoriginnode) {
     45 	dns_db_t *db = NULL;
     46 	dns_dbnode_t *node = NULL;
     47 	isc_result_t result;
     48 
     49 	UNUSED(state);
     50 
     51 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
     52 			       dns_rdataclass_in, 0, NULL, &db);
     53 	assert_int_equal(result, ISC_R_SUCCESS);
     54 
     55 	result = dns_db_getoriginnode(db, &node);
     56 	assert_int_equal(result, ISC_R_SUCCESS);
     57 	dns_db_detachnode(db, &node);
     58 
     59 	result = dns_db_getoriginnode(db, &node);
     60 	assert_int_equal(result, ISC_R_SUCCESS);
     61 	dns_db_detachnode(db, &node);
     62 
     63 	dns_db_detach(&db);
     64 }
     65 
     66 /* test getservestalettl and setservestalettl */
     67 ISC_RUN_TEST_IMPL(getsetservestalettl) {
     68 	dns_db_t *db = NULL;
     69 	isc_result_t result;
     70 	dns_ttl_t ttl;
     71 
     72 	UNUSED(state);
     73 
     74 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache,
     75 			       dns_rdataclass_in, 0, NULL, &db);
     76 	assert_int_equal(result, ISC_R_SUCCESS);
     77 
     78 	ttl = 5000;
     79 	result = dns_db_getservestalettl(db, &ttl);
     80 	assert_int_equal(result, ISC_R_SUCCESS);
     81 	assert_int_equal(ttl, 0);
     82 
     83 	ttl = 6 * 3600;
     84 	result = dns_db_setservestalettl(db, ttl);
     85 	assert_int_equal(result, ISC_R_SUCCESS);
     86 
     87 	ttl = 5000;
     88 	result = dns_db_getservestalettl(db, &ttl);
     89 	assert_int_equal(result, ISC_R_SUCCESS);
     90 	assert_int_equal(ttl, 6 * 3600);
     91 
     92 	dns_db_detach(&db);
     93 }
     94 
     95 /* check DNS_DBFIND_STALEOK works */
     96 ISC_RUN_TEST_IMPL(dns_dbfind_staleok) {
     97 	dns_db_t *db = NULL;
     98 	dns_dbnode_t *node = NULL;
     99 	dns_fixedname_t example_fixed;
    100 	dns_fixedname_t found_fixed;
    101 	dns_name_t *example;
    102 	dns_name_t *found;
    103 	dns_rdatalist_t rdatalist;
    104 	dns_rdataset_t rdataset;
    105 	int count;
    106 	int pass;
    107 	isc_result_t result;
    108 	unsigned char data[] = { 0x0a, 0x00, 0x00, 0x01 };
    109 
    110 	UNUSED(state);
    111 
    112 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache,
    113 			       dns_rdataclass_in, 0, NULL, &db);
    114 	assert_int_equal(result, ISC_R_SUCCESS);
    115 
    116 	example = dns_fixedname_initname(&example_fixed);
    117 	found = dns_fixedname_initname(&found_fixed);
    118 
    119 	result = dns_name_fromstring(example, "example", 0, NULL);
    120 	assert_int_equal(result, ISC_R_SUCCESS);
    121 
    122 	/*
    123 	 * Pass 0: default; no stale processing permitted.
    124 	 * Pass 1: stale processing for 1 second.
    125 	 * Pass 2: stale turned off after being on.
    126 	 */
    127 	for (pass = 0; pass < 3; pass++) {
    128 		dns_rdata_t rdata = DNS_RDATA_INIT;
    129 
    130 		/* 10.0.0.1 */
    131 		rdata.data = data;
    132 		rdata.length = 4;
    133 		rdata.rdclass = dns_rdataclass_in;
    134 		rdata.type = dns_rdatatype_a;
    135 
    136 		dns_rdatalist_init(&rdatalist);
    137 		rdatalist.ttl = 2;
    138 		rdatalist.type = dns_rdatatype_a;
    139 		rdatalist.rdclass = dns_rdataclass_in;
    140 		ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
    141 
    142 		switch (pass) {
    143 		case 0:
    144 			/* default: stale processing off */
    145 			break;
    146 		case 1:
    147 			/* turn on stale processing */
    148 			result = dns_db_setservestalettl(db, 1);
    149 			assert_int_equal(result, ISC_R_SUCCESS);
    150 			break;
    151 		case 2:
    152 			/* turn off stale processing */
    153 			result = dns_db_setservestalettl(db, 0);
    154 			assert_int_equal(result, ISC_R_SUCCESS);
    155 			break;
    156 		}
    157 
    158 		dns_rdataset_init(&rdataset);
    159 		result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
    160 		assert_int_equal(result, ISC_R_SUCCESS);
    161 
    162 		result = dns_db_findnode(db, example, true, &node);
    163 		assert_int_equal(result, ISC_R_SUCCESS);
    164 
    165 		result = dns_db_addrdataset(db, node, NULL, 0, &rdataset, 0,
    166 					    NULL);
    167 		assert_int_equal(result, ISC_R_SUCCESS);
    168 
    169 		dns_db_detachnode(db, &node);
    170 		dns_rdataset_disassociate(&rdataset);
    171 
    172 		result = dns_db_find(db, example, NULL, dns_rdatatype_a, 0, 0,
    173 				     &node, found, &rdataset, NULL);
    174 		assert_int_equal(result, ISC_R_SUCCESS);
    175 
    176 		/*
    177 		 * May loop for up to 2 seconds performing non stale lookups.
    178 		 */
    179 		count = 0;
    180 		do {
    181 			count++;
    182 			assert_in_range(count, 1, 21); /* loop sanity */
    183 			assert_int_equal(rdataset.attributes &
    184 						 DNS_RDATASETATTR_STALE,
    185 					 0);
    186 			assert_true(rdataset.ttl > 0);
    187 			dns_db_detachnode(db, &node);
    188 			dns_rdataset_disassociate(&rdataset);
    189 
    190 			usleep(100000); /* 100 ms */
    191 
    192 			result = dns_db_find(db, example, NULL, dns_rdatatype_a,
    193 					     0, 0, &node, found, &rdataset,
    194 					     NULL);
    195 		} while (result == ISC_R_SUCCESS);
    196 
    197 		assert_int_equal(result, ISC_R_NOTFOUND);
    198 
    199 		/*
    200 		 * Check whether we can get stale data.
    201 		 */
    202 		result = dns_db_find(db, example, NULL, dns_rdatatype_a,
    203 				     DNS_DBFIND_STALEOK, 0, &node, found,
    204 				     &rdataset, NULL);
    205 		switch (pass) {
    206 		case 0:
    207 			assert_int_equal(result, ISC_R_NOTFOUND);
    208 			break;
    209 		case 1:
    210 			/*
    211 			 * Should loop for 1 second with stale lookups then
    212 			 * stop.
    213 			 */
    214 			count = 0;
    215 			do {
    216 				count++;
    217 				assert_in_range(count, 0, 49); /* loop sanity */
    218 				assert_int_equal(result, ISC_R_SUCCESS);
    219 				assert_int_equal(rdataset.attributes &
    220 							 DNS_RDATASETATTR_STALE,
    221 						 DNS_RDATASETATTR_STALE);
    222 				dns_db_detachnode(db, &node);
    223 				dns_rdataset_disassociate(&rdataset);
    224 
    225 				usleep(100000); /* 100 ms */
    226 
    227 				result = dns_db_find(
    228 					db, example, NULL, dns_rdatatype_a,
    229 					DNS_DBFIND_STALEOK, 0, &node, found,
    230 					&rdataset, NULL);
    231 			} while (result == ISC_R_SUCCESS);
    232 			/*
    233 			 * usleep(100000) can be slightly less than 10ms so
    234 			 * allow the count to reach 11.
    235 			 */
    236 			assert_in_range(count, 1, 11);
    237 			assert_int_equal(result, ISC_R_NOTFOUND);
    238 			break;
    239 		case 2:
    240 			assert_int_equal(result, ISC_R_NOTFOUND);
    241 			break;
    242 		}
    243 	}
    244 
    245 	dns_db_detach(&db);
    246 }
    247 
    248 /* database class */
    249 ISC_RUN_TEST_IMPL(class) {
    250 	isc_result_t result;
    251 	dns_db_t *db = NULL;
    252 
    253 	UNUSED(state);
    254 
    255 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
    256 			       dns_rdataclass_in, 0, NULL, &db);
    257 	assert_int_equal(result, ISC_R_SUCCESS);
    258 
    259 	result = dns_db_load(db, TESTS_DIR "/testdata/db/data.db",
    260 			     dns_masterformat_text, 0);
    261 	assert_int_equal(result, ISC_R_SUCCESS);
    262 
    263 	assert_int_equal(dns_db_class(db), dns_rdataclass_in);
    264 
    265 	dns_db_detach(&db);
    266 }
    267 
    268 /* database type */
    269 ISC_RUN_TEST_IMPL(dbtype) {
    270 	isc_result_t result;
    271 	dns_db_t *db = NULL;
    272 
    273 	UNUSED(state);
    274 
    275 	/* DB has zone semantics */
    276 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
    277 			       dns_rdataclass_in, 0, NULL, &db);
    278 	assert_int_equal(result, ISC_R_SUCCESS);
    279 	result = dns_db_load(db, TESTS_DIR "/testdata/db/data.db",
    280 			     dns_masterformat_text, 0);
    281 	assert_int_equal(result, ISC_R_SUCCESS);
    282 	assert_true(dns_db_iszone(db));
    283 	assert_false(dns_db_iscache(db));
    284 	dns_db_detach(&db);
    285 
    286 	/* DB has cache semantics */
    287 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache,
    288 			       dns_rdataclass_in, 0, NULL, &db);
    289 	assert_int_equal(result, ISC_R_SUCCESS);
    290 	result = dns_db_load(db, TESTS_DIR "/testdata/db/data.db",
    291 			     dns_masterformat_text, 0);
    292 	assert_int_equal(result, ISC_R_SUCCESS);
    293 	assert_true(dns_db_iscache(db));
    294 	assert_false(dns_db_iszone(db));
    295 	dns_db_detach(&db);
    296 }
    297 
    298 /* database versions */
    299 ISC_RUN_TEST_IMPL(version) {
    300 	isc_result_t result;
    301 	dns_fixedname_t fname, ffound;
    302 	dns_name_t *name, *foundname;
    303 	dns_db_t *db = NULL;
    304 	dns_dbversion_t *ver = NULL, *new = NULL;
    305 	dns_dbnode_t *node = NULL;
    306 	dns_rdataset_t rdataset;
    307 
    308 	UNUSED(state);
    309 
    310 	result = dns_test_loaddb(&db, dns_dbtype_zone, "test.test",
    311 				 TESTS_DIR "/testdata/db/data.db");
    312 	assert_int_equal(result, ISC_R_SUCCESS);
    313 
    314 	/* Open current version for reading */
    315 	dns_db_currentversion(db, &ver);
    316 	dns_test_namefromstring("b.test.test", &fname);
    317 	name = dns_fixedname_name(&fname);
    318 	foundname = dns_fixedname_initname(&ffound);
    319 	dns_rdataset_init(&rdataset);
    320 	result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node,
    321 			     foundname, &rdataset, NULL);
    322 	assert_int_equal(result, ISC_R_SUCCESS);
    323 	dns_rdataset_disassociate(&rdataset);
    324 	dns_db_detachnode(db, &node);
    325 	dns_db_closeversion(db, &ver, false);
    326 
    327 	/* Open new version for writing */
    328 	dns_db_currentversion(db, &ver);
    329 	dns_test_namefromstring("b.test.test", &fname);
    330 	name = dns_fixedname_name(&fname);
    331 	foundname = dns_fixedname_initname(&ffound);
    332 	dns_rdataset_init(&rdataset);
    333 	result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node,
    334 			     foundname, &rdataset, NULL);
    335 	assert_int_equal(result, ISC_R_SUCCESS);
    336 
    337 	result = dns_db_newversion(db, &new);
    338 	assert_int_equal(result, ISC_R_SUCCESS);
    339 
    340 	/* Delete the rdataset from the new version */
    341 	result = dns_db_deleterdataset(db, node, new, dns_rdatatype_a, 0);
    342 	assert_int_equal(result, ISC_R_SUCCESS);
    343 
    344 	dns_rdataset_disassociate(&rdataset);
    345 	dns_db_detachnode(db, &node);
    346 
    347 	/* This should fail now */
    348 	result = dns_db_find(db, name, new, dns_rdatatype_a, 0, 0, &node,
    349 			     foundname, &rdataset, NULL);
    350 	assert_int_equal(result, DNS_R_NXDOMAIN);
    351 
    352 	dns_db_closeversion(db, &new, true);
    353 
    354 	/* But this should still succeed */
    355 	result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node,
    356 			     foundname, &rdataset, NULL);
    357 	assert_int_equal(result, ISC_R_SUCCESS);
    358 	dns_rdataset_disassociate(&rdataset);
    359 	dns_db_detachnode(db, &node);
    360 	dns_db_closeversion(db, &ver, false);
    361 
    362 	dns_db_detach(&db);
    363 }
    364 
    365 ISC_TEST_LIST_START
    366 ISC_TEST_ENTRY(getoriginnode)
    367 ISC_TEST_ENTRY(getsetservestalettl)
    368 ISC_TEST_ENTRY(dns_dbfind_staleok)
    369 ISC_TEST_ENTRY(class)
    370 ISC_TEST_ENTRY(dbtype)
    371 ISC_TEST_ENTRY(version)
    372 ISC_TEST_LIST_END
    373 
    374 ISC_TEST_MAIN
    375