xref: /netbsd-src/external/mpl/bind/dist/tests/dns/name_test.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /*	$NetBSD: name_test.c,v 1.3 2024/09/22 00:14:11 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 <stdbool.h>
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #define UNIT_TESTING
27 #include <cmocka.h>
28 
29 #include <isc/buffer.h>
30 #include <isc/commandline.h>
31 #include <isc/mem.h>
32 #include <isc/os.h>
33 #include <isc/print.h>
34 #include <isc/thread.h>
35 #include <isc/util.h>
36 
37 #include <dns/compress.h>
38 #include <dns/fixedname.h>
39 #include <dns/name.h>
40 
41 #include <tests/dns.h>
42 
43 /* Set to true (or use -v option) for verbose output */
44 static bool verbose = false;
45 
46 /* dns_name_fullcompare test */
47 ISC_RUN_TEST_IMPL(fullcompare) {
48 	dns_fixedname_t fixed1;
49 	dns_fixedname_t fixed2;
50 	dns_name_t *name1;
51 	dns_name_t *name2;
52 	dns_namereln_t relation;
53 	int i;
54 	isc_result_t result;
55 	struct {
56 		const char *name1;
57 		const char *name2;
58 		dns_namereln_t relation;
59 		int order;
60 		unsigned int nlabels;
61 	} data[] = {
62 		/* relative */
63 		{ "", "", dns_namereln_equal, 0, 0 },
64 		{ "foo", "", dns_namereln_subdomain, 1, 0 },
65 		{ "", "foo", dns_namereln_contains, -1, 0 },
66 		{ "foo", "bar", dns_namereln_none, 4, 0 },
67 		{ "bar", "foo", dns_namereln_none, -4, 0 },
68 		{ "bar.foo", "foo", dns_namereln_subdomain, 1, 1 },
69 		{ "foo", "bar.foo", dns_namereln_contains, -1, 1 },
70 		{ "baz.bar.foo", "bar.foo", dns_namereln_subdomain, 1, 2 },
71 		{ "bar.foo", "baz.bar.foo", dns_namereln_contains, -1, 2 },
72 		{ "foo.example", "bar.example", dns_namereln_commonancestor, 4,
73 		  1 },
74 
75 		/* absolute */
76 		{ ".", ".", dns_namereln_equal, 0, 1 },
77 		{ "foo.", "bar.", dns_namereln_commonancestor, 4, 1 },
78 		{ "bar.", "foo.", dns_namereln_commonancestor, -4, 1 },
79 		{ "foo.example.", "bar.example.", dns_namereln_commonancestor,
80 		  4, 2 },
81 		{ "bar.foo.", "foo.", dns_namereln_subdomain, 1, 2 },
82 		{ "foo.", "bar.foo.", dns_namereln_contains, -1, 2 },
83 		{ "baz.bar.foo.", "bar.foo.", dns_namereln_subdomain, 1, 3 },
84 		{ "bar.foo.", "baz.bar.foo.", dns_namereln_contains, -1, 3 },
85 		{ NULL, NULL, dns_namereln_none, 0, 0 }
86 	};
87 
88 	UNUSED(state);
89 
90 	name1 = dns_fixedname_initname(&fixed1);
91 	name2 = dns_fixedname_initname(&fixed2);
92 	for (i = 0; data[i].name1 != NULL; i++) {
93 		int order = 3000;
94 		unsigned int nlabels = 3000;
95 
96 		if (data[i].name1[0] == 0) {
97 			dns_fixedname_init(&fixed1);
98 		} else {
99 			result = dns_name_fromstring2(name1, data[i].name1,
100 						      NULL, 0, NULL);
101 			assert_int_equal(result, ISC_R_SUCCESS);
102 		}
103 		if (data[i].name2[0] == 0) {
104 			dns_fixedname_init(&fixed2);
105 		} else {
106 			result = dns_name_fromstring2(name2, data[i].name2,
107 						      NULL, 0, NULL);
108 			assert_int_equal(result, ISC_R_SUCCESS);
109 		}
110 		relation = dns_name_fullcompare(name1, name1, &order, &nlabels);
111 		assert_int_equal(relation, dns_namereln_equal);
112 		assert_int_equal(order, 0);
113 		assert_int_equal(nlabels, name1->labels);
114 
115 		/* Some random initializer */
116 		order = 3001;
117 		nlabels = 3001;
118 
119 		relation = dns_name_fullcompare(name1, name2, &order, &nlabels);
120 		assert_int_equal(relation, data[i].relation);
121 		assert_int_equal(order, data[i].order);
122 		assert_int_equal(nlabels, data[i].nlabels);
123 	}
124 }
125 
126 static void
127 compress_test(dns_name_t *name1, dns_name_t *name2, dns_name_t *name3,
128 	      unsigned char *expected, unsigned int length,
129 	      dns_compress_t *cctx, dns_decompress_t *dctx) {
130 	isc_buffer_t source;
131 	isc_buffer_t target;
132 	dns_name_t name;
133 	unsigned char buf1[1024];
134 	unsigned char buf2[1024];
135 
136 	isc_buffer_init(&source, buf1, sizeof(buf1));
137 	isc_buffer_init(&target, buf2, sizeof(buf2));
138 
139 	assert_int_equal(dns_name_towire(name1, cctx, &source), ISC_R_SUCCESS);
140 
141 	assert_int_equal(dns_name_towire(name2, cctx, &source), ISC_R_SUCCESS);
142 	assert_int_equal(dns_name_towire(name2, cctx, &source), ISC_R_SUCCESS);
143 	assert_int_equal(dns_name_towire(name3, cctx, &source), ISC_R_SUCCESS);
144 
145 	isc_buffer_setactive(&source, source.used);
146 
147 	dns_name_init(&name, NULL);
148 	RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
149 		      ISC_R_SUCCESS);
150 	RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
151 		      ISC_R_SUCCESS);
152 	RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
153 		      ISC_R_SUCCESS);
154 	RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
155 		      ISC_R_SUCCESS);
156 	dns_decompress_invalidate(dctx);
157 
158 	assert_int_equal(target.used, length);
159 	assert_true(memcmp(target.base, expected, target.used) == 0);
160 }
161 
162 /* name compression test */
163 ISC_RUN_TEST_IMPL(compression) {
164 	unsigned int allowed;
165 	dns_compress_t cctx;
166 	dns_decompress_t dctx;
167 	dns_name_t name1;
168 	dns_name_t name2;
169 	dns_name_t name3;
170 	isc_region_t r;
171 	unsigned char plain1[] = "\003yyy\003foo";
172 	unsigned char plain2[] = "\003bar\003yyy\003foo";
173 	unsigned char plain3[] = "\003xxx\003bar\003foo";
174 	unsigned char plain[] = "\003yyy\003foo\0\003bar\003yyy\003foo\0\003"
175 				"bar\003yyy\003foo\0\003xxx\003bar\003foo";
176 
177 	UNUSED(state);
178 
179 	dns_name_init(&name1, NULL);
180 	r.base = plain1;
181 	r.length = sizeof(plain1);
182 	dns_name_fromregion(&name1, &r);
183 
184 	dns_name_init(&name2, NULL);
185 	r.base = plain2;
186 	r.length = sizeof(plain2);
187 	dns_name_fromregion(&name2, &r);
188 
189 	dns_name_init(&name3, NULL);
190 	r.base = plain3;
191 	r.length = sizeof(plain3);
192 	dns_name_fromregion(&name3, &r);
193 
194 	/* Test 1: NONE */
195 	allowed = DNS_COMPRESS_NONE;
196 	assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS);
197 	dns_compress_setmethods(&cctx, allowed);
198 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
199 	dns_decompress_setmethods(&dctx, allowed);
200 
201 	compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx,
202 		      &dctx);
203 
204 	dns_compress_rollback(&cctx, 0);
205 	dns_compress_invalidate(&cctx);
206 
207 	/* Test2: GLOBAL14 */
208 	allowed = DNS_COMPRESS_GLOBAL14;
209 	assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS);
210 	dns_compress_setmethods(&cctx, allowed);
211 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
212 	dns_decompress_setmethods(&dctx, allowed);
213 
214 	compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx,
215 		      &dctx);
216 
217 	dns_compress_rollback(&cctx, 0);
218 	dns_compress_invalidate(&cctx);
219 
220 	/* Test3: ALL */
221 	allowed = DNS_COMPRESS_ALL;
222 	assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS);
223 	dns_compress_setmethods(&cctx, allowed);
224 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
225 	dns_decompress_setmethods(&dctx, allowed);
226 
227 	compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx,
228 		      &dctx);
229 
230 	dns_compress_rollback(&cctx, 0);
231 	dns_compress_invalidate(&cctx);
232 
233 	/* Test4: NONE disabled */
234 	allowed = DNS_COMPRESS_NONE;
235 	assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS);
236 	dns_compress_setmethods(&cctx, allowed);
237 	dns_compress_disable(&cctx);
238 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
239 	dns_decompress_setmethods(&dctx, allowed);
240 
241 	compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx,
242 		      &dctx);
243 
244 	dns_compress_rollback(&cctx, 0);
245 	dns_compress_invalidate(&cctx);
246 
247 	/* Test5: GLOBAL14 disabled */
248 	allowed = DNS_COMPRESS_GLOBAL14;
249 	assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS);
250 	dns_compress_setmethods(&cctx, allowed);
251 	dns_compress_disable(&cctx);
252 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
253 	dns_decompress_setmethods(&dctx, allowed);
254 
255 	compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx,
256 		      &dctx);
257 
258 	dns_compress_rollback(&cctx, 0);
259 	dns_compress_invalidate(&cctx);
260 
261 	/* Test6: ALL disabled */
262 	allowed = DNS_COMPRESS_ALL;
263 	assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS);
264 	dns_compress_setmethods(&cctx, allowed);
265 	dns_compress_disable(&cctx);
266 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
267 	dns_decompress_setmethods(&dctx, allowed);
268 
269 	compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx,
270 		      &dctx);
271 
272 	dns_compress_rollback(&cctx, 0);
273 	dns_compress_invalidate(&cctx);
274 }
275 
276 ISC_RUN_TEST_IMPL(fromregion) {
277 	dns_name_t name;
278 	isc_buffer_t b;
279 	isc_region_t r;
280 	/*
281 	 * target and source need to be bigger than DNS_NAME_MAXWIRE to
282 	 * exercise 'len > DNS_NAME_MAXWIRE' test in dns_name_fromwire
283 	 */
284 	unsigned char target[DNS_NAME_MAXWIRE + 10];
285 	unsigned char source[DNS_NAME_MAXWIRE + 10] = { '\007', 'e', 'x', 'a',
286 							'm',	'p', 'l', 'e' };
287 	/*
288 	 * Extract the fully qualified name at the beginning of 'source'
289 	 * into 'name' where 'name.ndata' points to the buffer 'target'.
290 	 */
291 	isc_buffer_init(&b, target, sizeof(target));
292 	dns_name_init(&name, NULL);
293 	dns_name_setbuffer(&name, &b);
294 	r.base = source;
295 	r.length = sizeof(source);
296 	dns_name_fromregion(&name, &r);
297 	assert_int_equal(9, name.length);
298 	assert_ptr_equal(target, name.ndata);
299 	assert_true(dns_name_isabsolute(&name));
300 
301 	/*
302 	 * Extract the fully qualified name at the beginning of 'source'
303 	 * into 'name' where 'name.ndata' points to the source.
304 	 */
305 	isc_buffer_init(&b, target, sizeof(target));
306 	dns_name_init(&name, NULL);
307 	r.base = source;
308 	r.length = sizeof(source);
309 	dns_name_fromregion(&name, &r);
310 	assert_int_equal(9, name.length);
311 	assert_ptr_equal(source, name.ndata);
312 	assert_true(dns_name_isabsolute(&name));
313 
314 	/*
315 	 * Extract the partially qualified name in 'source' into 'name'
316 	 * where 'name.ndata' points to the source.
317 	 */
318 	isc_buffer_init(&b, target, sizeof(target));
319 	dns_name_init(&name, NULL);
320 	r.base = source;
321 	r.length = 8;
322 	dns_name_fromregion(&name, &r);
323 	assert_int_equal(8, name.length);
324 	assert_ptr_equal(source, name.ndata);
325 	assert_false(dns_name_isabsolute(&name));
326 
327 	/*
328 	 * Extract empty name in 'source' into 'name'.
329 	 */
330 	isc_buffer_init(&b, target, sizeof(target));
331 	dns_name_init(&name, NULL);
332 	r.base = source;
333 	r.length = 0;
334 	dns_name_fromregion(&name, &r);
335 	assert_int_equal(0, name.length);
336 	assert_ptr_equal(source, name.ndata);
337 	assert_false(dns_name_isabsolute(&name));
338 }
339 
340 /* is trust-anchor-telemetry test */
341 ISC_RUN_TEST_IMPL(istat) {
342 	dns_fixedname_t fixed;
343 	dns_name_t *name;
344 	isc_result_t result;
345 	size_t i;
346 	struct {
347 		const char *name;
348 		bool istat;
349 	} data[] = { { ".", false },
350 		     { "_ta-", false },
351 		     { "_ta-1234", true },
352 		     { "_TA-1234", true },
353 		     { "+TA-1234", false },
354 		     { "_fa-1234", false },
355 		     { "_td-1234", false },
356 		     { "_ta_1234", false },
357 		     { "_ta-g234", false },
358 		     { "_ta-1h34", false },
359 		     { "_ta-12i4", false },
360 		     { "_ta-123j", false },
361 		     { "_ta-1234-abcf", true },
362 		     { "_ta-1234-abcf-ED89", true },
363 		     { "_ta-12345-abcf-ED89", false },
364 		     { "_ta-.example", false },
365 		     { "_ta-1234.example", true },
366 		     { "_ta-1234-abcf.example", true },
367 		     { "_ta-1234-abcf-ED89.example", true },
368 		     { "_ta-12345-abcf-ED89.example", false },
369 		     { "_ta-1234-abcfe-ED89.example", false },
370 		     { "_ta-1234-abcf-EcD89.example", false } };
371 
372 	UNUSED(state);
373 
374 	name = dns_fixedname_initname(&fixed);
375 
376 	for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) {
377 		result = dns_name_fromstring(name, data[i].name, 0, NULL);
378 		assert_int_equal(result, ISC_R_SUCCESS);
379 		assert_int_equal(dns_name_istat(name), data[i].istat);
380 	}
381 }
382 
383 /* dns_nane_init */
384 ISC_RUN_TEST_IMPL(init) {
385 	dns_name_t name;
386 	unsigned char offsets[1];
387 
388 	UNUSED(state);
389 
390 	dns_name_init(&name, offsets);
391 
392 	assert_null(name.ndata);
393 	assert_int_equal(name.length, 0);
394 	assert_int_equal(name.labels, 0);
395 	assert_int_equal(name.attributes, 0);
396 	assert_ptr_equal(name.offsets, offsets);
397 	assert_null(name.buffer);
398 }
399 
400 /* dns_nane_invalidate */
401 ISC_RUN_TEST_IMPL(invalidate) {
402 	dns_name_t name;
403 	unsigned char offsets[1];
404 
405 	UNUSED(state);
406 
407 	dns_name_init(&name, offsets);
408 	dns_name_invalidate(&name);
409 
410 	assert_null(name.ndata);
411 	assert_int_equal(name.length, 0);
412 	assert_int_equal(name.labels, 0);
413 	assert_int_equal(name.attributes, 0);
414 	assert_null(name.offsets);
415 	assert_null(name.buffer);
416 }
417 
418 /* dns_nane_setbuffer/hasbuffer */
419 ISC_RUN_TEST_IMPL(buffer) {
420 	dns_name_t name;
421 	unsigned char buf[BUFSIZ];
422 	isc_buffer_t b;
423 
424 	UNUSED(state);
425 
426 	isc_buffer_init(&b, buf, BUFSIZ);
427 	dns_name_init(&name, NULL);
428 	dns_name_setbuffer(&name, &b);
429 	assert_ptr_equal(name.buffer, &b);
430 	assert_true(dns_name_hasbuffer(&name));
431 }
432 
433 /* dns_nane_isabsolute */
434 ISC_RUN_TEST_IMPL(isabsolute) {
435 	struct {
436 		const char *namestr;
437 		bool expect;
438 	} testcases[] = { { "x", false },
439 			  { "a.b.c.d.", true },
440 			  { "x.z", false } };
441 	unsigned int i;
442 
443 	UNUSED(state);
444 
445 	for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) {
446 		isc_result_t result;
447 		dns_name_t name;
448 		unsigned char data[BUFSIZ];
449 		isc_buffer_t b, nb;
450 		size_t len;
451 
452 		len = strlen(testcases[i].namestr);
453 		isc_buffer_constinit(&b, testcases[i].namestr, len);
454 		isc_buffer_add(&b, len);
455 
456 		dns_name_init(&name, NULL);
457 		isc_buffer_init(&nb, data, BUFSIZ);
458 		dns_name_setbuffer(&name, &nb);
459 		result = dns_name_fromtext(&name, &b, NULL, 0, NULL);
460 		assert_int_equal(result, ISC_R_SUCCESS);
461 
462 		assert_int_equal(dns_name_isabsolute(&name),
463 				 testcases[i].expect);
464 	}
465 }
466 
467 /* dns_nane_hash */
468 ISC_RUN_TEST_IMPL(hash) {
469 	struct {
470 		const char *name1;
471 		const char *name2;
472 		bool expect;
473 		bool expecti;
474 	} testcases[] = {
475 		{ "a.b.c.d", "A.B.C.D", true, false },
476 		{ "a.b.c.d.", "A.B.C.D.", true, false },
477 		{ "a.b.c.d", "a.b.c.d", true, true },
478 		{ "A.B.C.D.", "A.B.C.D.", true, false },
479 		{ "x.y.z.w", "a.b.c.d", false, false },
480 		{ "x.y.z.w.", "a.b.c.d.", false, false },
481 	};
482 	unsigned int i;
483 
484 	UNUSED(state);
485 
486 	for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) {
487 		isc_result_t result;
488 		dns_fixedname_t f1, f2;
489 		dns_name_t *n1, *n2;
490 		unsigned int h1, h2;
491 
492 		n1 = dns_fixedname_initname(&f1);
493 		n2 = dns_fixedname_initname(&f2);
494 
495 		result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0,
496 					      NULL);
497 		assert_int_equal(result, ISC_R_SUCCESS);
498 		result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0,
499 					      NULL);
500 		assert_int_equal(result, ISC_R_SUCCESS);
501 
502 		/* Check case-insensitive hashing first */
503 		h1 = dns_name_hash(n1, false);
504 		h2 = dns_name_hash(n2, false);
505 
506 		if (verbose) {
507 			print_message("# %s hashes to %u, "
508 				      "%s to %u, case insensitive\n",
509 				      testcases[i].name1, h1,
510 				      testcases[i].name2, h2);
511 		}
512 
513 		assert_int_equal((h1 == h2), testcases[i].expect);
514 
515 		/* Now case-sensitive */
516 		h1 = dns_name_hash(n1, false);
517 		h2 = dns_name_hash(n2, false);
518 
519 		if (verbose) {
520 			print_message("# %s hashes to %u, "
521 				      "%s to %u, case sensitive\n",
522 				      testcases[i].name1, h1,
523 				      testcases[i].name2, h2);
524 		}
525 
526 		assert_int_equal((h1 == h2), testcases[i].expect);
527 	}
528 }
529 
530 /* dns_nane_issubdomain */
531 ISC_RUN_TEST_IMPL(issubdomain) {
532 	struct {
533 		const char *name1;
534 		const char *name2;
535 		bool expect;
536 	} testcases[] = {
537 		{ "c.d", "a.b.c.d", false }, { "c.d.", "a.b.c.d.", false },
538 		{ "b.c.d", "c.d", true },    { "a.b.c.d.", "c.d.", true },
539 		{ "a.b.c", "a.b.c", true },  { "a.b.c.", "a.b.c.", true },
540 		{ "x.y.z", "a.b.c", false }
541 	};
542 	unsigned int i;
543 
544 	UNUSED(state);
545 
546 	for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) {
547 		isc_result_t result;
548 		dns_fixedname_t f1, f2;
549 		dns_name_t *n1, *n2;
550 
551 		n1 = dns_fixedname_initname(&f1);
552 		n2 = dns_fixedname_initname(&f2);
553 
554 		result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0,
555 					      NULL);
556 		assert_int_equal(result, ISC_R_SUCCESS);
557 		result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0,
558 					      NULL);
559 		assert_int_equal(result, ISC_R_SUCCESS);
560 
561 		if (verbose) {
562 			print_message("# check: %s %s a subdomain of %s\n",
563 				      testcases[i].name1,
564 				      testcases[i].expect ? "is" : "is not",
565 				      testcases[i].name2);
566 		}
567 
568 		assert_int_equal(dns_name_issubdomain(n1, n2),
569 				 testcases[i].expect);
570 	}
571 }
572 
573 /* dns_nane_countlabels */
574 ISC_RUN_TEST_IMPL(countlabels) {
575 	struct {
576 		const char *namestr;
577 		unsigned int expect;
578 	} testcases[] = {
579 		{ "c.d", 2 },	  { "c.d.", 3 },  { "a.b.c.d.", 5 },
580 		{ "a.b.c.d", 4 }, { "a.b.c", 3 }, { ".", 1 },
581 	};
582 	unsigned int i;
583 
584 	UNUSED(state);
585 
586 	for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) {
587 		isc_result_t result;
588 		dns_fixedname_t fname;
589 		dns_name_t *name;
590 
591 		name = dns_fixedname_initname(&fname);
592 
593 		result = dns_name_fromstring2(name, testcases[i].namestr, NULL,
594 					      0, NULL);
595 		assert_int_equal(result, ISC_R_SUCCESS);
596 
597 		if (verbose) {
598 			print_message("# %s: expect %u labels\n",
599 				      testcases[i].namestr,
600 				      testcases[i].expect);
601 		}
602 
603 		assert_int_equal(dns_name_countlabels(name),
604 				 testcases[i].expect);
605 	}
606 }
607 
608 /* dns_nane_getlabel */
609 ISC_RUN_TEST_IMPL(getlabel) {
610 	struct {
611 		const char *name1;
612 		unsigned int pos1;
613 		const char *name2;
614 		unsigned int pos2;
615 	} testcases[] = {
616 		{ "c.d", 1, "a.b.c.d", 3 },
617 		{ "a.b.c.d", 3, "c.d", 1 },
618 		{ "a.b.c.", 3, "A.B.C.", 3 },
619 	};
620 	unsigned int i;
621 
622 	UNUSED(state);
623 
624 	for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) {
625 		isc_result_t result;
626 		dns_fixedname_t f1, f2;
627 		dns_name_t *n1, *n2;
628 		dns_label_t l1, l2;
629 		unsigned int j;
630 
631 		n1 = dns_fixedname_initname(&f1);
632 		n2 = dns_fixedname_initname(&f2);
633 
634 		result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0,
635 					      NULL);
636 		assert_int_equal(result, ISC_R_SUCCESS);
637 		result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0,
638 					      NULL);
639 		assert_int_equal(result, ISC_R_SUCCESS);
640 
641 		dns_name_getlabel(n1, testcases[i].pos1, &l1);
642 		dns_name_getlabel(n2, testcases[i].pos2, &l2);
643 		assert_int_equal(l1.length, l2.length);
644 
645 		for (j = 0; j < l1.length; j++) {
646 			assert_int_equal(l1.base[j], l2.base[j]);
647 		}
648 	}
649 }
650 
651 /* dns_nane_getlabelsequence */
652 ISC_RUN_TEST_IMPL(getlabelsequence) {
653 	struct {
654 		const char *name1;
655 		unsigned int pos1;
656 		const char *name2;
657 		unsigned int pos2;
658 		unsigned int range;
659 	} testcases[] = {
660 		{ "c.d", 1, "a.b.c.d", 3, 1 },
661 		{ "a.b.c.d.e", 2, "c.d", 0, 2 },
662 		{ "a.b.c", 0, "a.b.c", 0, 3 },
663 	};
664 	unsigned int i;
665 
666 	UNUSED(state);
667 
668 	for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) {
669 		isc_result_t result;
670 		dns_name_t t1, t2;
671 		dns_fixedname_t f1, f2;
672 		dns_name_t *n1, *n2;
673 
674 		/* target names */
675 		dns_name_init(&t1, NULL);
676 		dns_name_init(&t2, NULL);
677 
678 		/* source names */
679 		n1 = dns_fixedname_initname(&f1);
680 		n2 = dns_fixedname_initname(&f2);
681 
682 		result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0,
683 					      NULL);
684 		assert_int_equal(result, ISC_R_SUCCESS);
685 		result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0,
686 					      NULL);
687 		assert_int_equal(result, ISC_R_SUCCESS);
688 
689 		dns_name_getlabelsequence(n1, testcases[i].pos1,
690 					  testcases[i].range, &t1);
691 		dns_name_getlabelsequence(n2, testcases[i].pos2,
692 					  testcases[i].range, &t2);
693 
694 		assert_true(dns_name_equal(&t1, &t2));
695 	}
696 }
697 
698 #ifdef DNS_BENCHMARK_TESTS
699 
700 /*
701  * XXXMUKS: Don't delete this code. It is useful in benchmarking the
702  * name parser, but we don't require it as part of the unit test runs.
703  */
704 
705 /* Benchmark dns_name_fromwire() implementation */
706 
707 ISC_RUN_TEST_IMPL(fromwire_thread(void *arg) {
708 	unsigned int maxval = 32000000;
709 	uint8_t data[] = { 3,	'w', 'w', 'w', 7,   'e', 'x',
710 			   'a', 'm', 'p', 'l', 'e', 7,	 'i',
711 			   'n', 'v', 'a', 'l', 'i', 'd', 0 };
712 	unsigned char output_data[DNS_NAME_MAXWIRE];
713 	isc_buffer_t source, target;
714 	unsigned int i;
715 	dns_decompress_t dctx;
716 
717 	UNUSED(arg);
718 
719 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
720 	dns_decompress_setmethods(&dctx, DNS_COMPRESS_NONE);
721 
722 	isc_buffer_init(&source, data, sizeof(data));
723 	isc_buffer_add(&source, sizeof(data));
724 	isc_buffer_init(&target, output_data, sizeof(output_data));
725 
726 	/* Parse 32 million names in each thread */
727 	for (i = 0; i < maxval; i++) {
728 		dns_name_t name;
729 
730 		isc_buffer_clear(&source);
731 		isc_buffer_clear(&target);
732 		isc_buffer_add(&source, sizeof(data));
733 		isc_buffer_setactive(&source, sizeof(data));
734 
735 		dns_name_init(&name, NULL);
736 		(void)dns_name_fromwire(&name, &source, &dctx, 0, &target);
737 	}
738 
739 	return (NULL);
740 }
741 
742 ISC_RUN_TEST_IMPL(benchmark) {
743 	isc_result_t result;
744 	unsigned int i;
745 	isc_time_t ts1, ts2;
746 	double t;
747 	unsigned int nthreads;
748 	isc_thread_t threads[32];
749 
750 	UNUSED(state);
751 
752 	debug_mem_record = false;
753 
754 	result = isc_time_now(&ts1);
755 	assert_int_equal(result, ISC_R_SUCCESS);
756 
757 	nthreads = ISC_MIN(isc_os_ncpus(), 32);
758 	nthreads = ISC_MAX(nthreads, 1);
759 	for (i = 0; i < nthreads; i++) {
760 		isc_thread_create(fromwire_thread, NULL, &threads[i]);
761 	}
762 
763 	for (i = 0; i < nthreads; i++) {
764 		isc_thread_join(threads[i], NULL);
765 	}
766 
767 	result = isc_time_now(&ts2);
768 	assert_int_equal(result, ISC_R_SUCCESS);
769 
770 	t = isc_time_microdiff(&ts2, &ts1);
771 
772 	printf("%u dns_name_fromwire() calls, %f seconds, %f calls/second\n",
773 	       nthreads * 32000000, t / 1000000.0,
774 	       (nthreads * 32000000) / (t / 1000000.0));
775 }
776 
777 #endif /* DNS_BENCHMARK_TESTS */
778 
779 ISC_TEST_LIST_START
780 ISC_TEST_ENTRY(fullcompare)
781 ISC_TEST_ENTRY(compression)
782 ISC_TEST_ENTRY(fromregion)
783 ISC_TEST_ENTRY(istat)
784 ISC_TEST_ENTRY(init)
785 ISC_TEST_ENTRY(invalidate)
786 ISC_TEST_ENTRY(buffer)
787 ISC_TEST_ENTRY(isabsolute)
788 ISC_TEST_ENTRY(hash)
789 ISC_TEST_ENTRY(issubdomain)
790 ISC_TEST_ENTRY(countlabels)
791 ISC_TEST_ENTRY(getlabel)
792 ISC_TEST_ENTRY(getlabelsequence)
793 #ifdef DNS_BENCHMARK_TESTS
794 ISC_TEST_ENTRY(benchmark)
795 #endif /* DNS_BENCHMARK_TESTS */
796 ISC_TEST_LIST_END
797 
798 ISC_TEST_MAIN
799