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