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