1 /*	$NetBSD: master_test.c,v 1.6 2015/07/08 17:28:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2011-2013, 2015  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id */
20 
21 /*! \file */
22 
23 #include <config.h>
24 
25 #include <atf-c.h>
26 
27 #include <stdio.h>
28 #include <unistd.h>
29 
30 #include <isc/print.h>
31 #include <isc/xml.h>
32 
33 #include <dns/cache.h>
34 #include <dns/callbacks.h>
35 #include <dns/db.h>
36 #include <dns/master.h>
37 #include <dns/masterdump.h>
38 #include <dns/name.h>
39 #include <dns/rdata.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 
43 #include "dnstest.h"
44 
45 /*
46  * Helper functions
47  */
48 
49 #define	BUFLEN		255
50 #define	BIGBUFLEN	(70 * 1024)
51 #define TEST_ORIGIN	"test"
52 
53 static dns_masterrawheader_t header;
54 static isc_boolean_t headerset;
55 
56 dns_name_t dns_origin;
57 char origin[sizeof(TEST_ORIGIN)];
58 unsigned char name_buf[BUFLEN];
59 dns_rdatacallbacks_t callbacks;
60 char *include_file = NULL;
61 
62 static isc_result_t
63 add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset);
64 
65 static void
66 rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *header);
67 
68 static isc_result_t
69 add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) {
70 	char buf[BIGBUFLEN];
71 	isc_buffer_t target;
72 	isc_result_t result;
73 
74 	UNUSED(arg);
75 
76 	isc_buffer_init(&target, buf, BIGBUFLEN);
77 	result = dns_rdataset_totext(dataset, owner, ISC_FALSE, ISC_FALSE,
78 				     &target);
79 	return(result);
80 }
81 
82 static void
83 rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *h) {
84 	UNUSED(zone);
85 	header = *h;
86 	headerset = ISC_TRUE;
87 }
88 
89 static isc_result_t
90 setup_master(void (*warn)(struct dns_rdatacallbacks *, const char *, ...),
91 	     void (*error)(struct dns_rdatacallbacks *, const char *, ...))
92 {
93 	isc_result_t		result;
94 	int			len;
95 	isc_buffer_t		source;
96 	isc_buffer_t		target;
97 
98 	strcpy(origin, TEST_ORIGIN);
99 	len = strlen(origin);
100 	isc_buffer_init(&source, origin, len);
101 	isc_buffer_add(&source, len);
102 	isc_buffer_setactive(&source, len);
103 	isc_buffer_init(&target, name_buf, BUFLEN);
104 	dns_name_init(&dns_origin, NULL);
105 	dns_master_initrawheader(&header);
106 
107 	result = dns_name_fromtext(&dns_origin, &source, dns_rootname,
108 				   0, &target);
109 	if (result != ISC_R_SUCCESS)
110 		return(result);
111 
112 	dns_rdatacallbacks_init_stdio(&callbacks);
113 	callbacks.add = add_callback;
114 	callbacks.rawdata = rawdata_callback;
115 	callbacks.zone = NULL;
116 	if (warn != NULL)
117 		callbacks.warn = warn;
118 	if (error != NULL)
119 		callbacks.error = error;
120 	headerset = ISC_FALSE;
121 	return (result);
122 }
123 
124 static isc_result_t
125 test_master(const char *testfile, dns_masterformat_t format,
126 	    void (*warn)(struct dns_rdatacallbacks *, const char *, ...),
127 	    void (*error)(struct dns_rdatacallbacks *, const char *, ...))
128 {
129 	isc_result_t		result;
130 
131 	result = setup_master(warn, error);
132 	if (result != ISC_R_SUCCESS)
133 		return(result);
134 
135 	result = dns_master_loadfile2(testfile, &dns_origin, &dns_origin,
136 				      dns_rdataclass_in, ISC_TRUE,
137 				      &callbacks, mctx, format);
138 	return (result);
139 }
140 
141 static void
142 include_callback(const char *filename, void *arg) {
143 	char **argp = (char **) arg;
144 	*argp = isc_mem_strdup(mctx, filename);
145 }
146 
147 /*
148  * Individual unit tests
149  */
150 
151 /* Successful load test */
152 ATF_TC(load);
153 ATF_TC_HEAD(load, tc) {
154 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a "
155 				       "valid master file and returns success");
156 }
157 ATF_TC_BODY(load, tc) {
158 	isc_result_t result;
159 
160 	UNUSED(tc);
161 
162 	result = dns_test_begin(NULL, ISC_FALSE);
163 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
164 
165 	result = test_master("testdata/master/master1.data",
166 			     dns_masterformat_text, NULL, NULL);
167 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
168 
169 	dns_test_end();
170 }
171 
172 
173 /* Unepxected end of file test */
174 ATF_TC(unexpected);
175 ATF_TC_HEAD(unexpected, tc) {
176 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns "
177 				       "DNS_R_UNEXPECTED when file ends "
178 				       "too soon");
179 }
180 ATF_TC_BODY(unexpected, tc) {
181 	isc_result_t result;
182 
183 	UNUSED(tc);
184 
185 	result = dns_test_begin(NULL, ISC_FALSE);
186 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
187 
188 	result = test_master("testdata/master/master2.data",
189 			     dns_masterformat_text, NULL, NULL);
190 	ATF_REQUIRE_EQ(result, ISC_R_UNEXPECTEDEND);
191 
192 	dns_test_end();
193 }
194 
195 
196 /* No owner test */
197 ATF_TC(noowner);
198 ATF_TC_HEAD(noowner, tc) {
199 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() accepts broken "
200 				       "zones with no TTL for first record "
201 				       "if it is an SOA");
202 }
203 ATF_TC_BODY(noowner, tc) {
204 	isc_result_t result;
205 
206 	UNUSED(tc);
207 
208 	result = dns_test_begin(NULL, ISC_FALSE);
209 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
210 
211 	result = test_master("testdata/master/master3.data",
212 			     dns_masterformat_text, NULL, NULL);
213 	ATF_REQUIRE_EQ(result, DNS_R_NOOWNER);
214 
215 	dns_test_end();
216 }
217 
218 
219 /* No TTL test */
220 ATF_TC(nottl);
221 ATF_TC_HEAD(nottl, tc) {
222 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns "
223 				       "DNS_R_NOOWNER when no owner name "
224 				       "is specified");
225 }
226 
227 ATF_TC_BODY(nottl, tc) {
228 	isc_result_t result;
229 
230 	UNUSED(tc);
231 
232 	result = dns_test_begin(NULL, ISC_FALSE);
233 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
234 
235 	result = test_master("testdata/master/master4.data",
236 			     dns_masterformat_text, NULL, NULL);
237 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
238 
239 	dns_test_end();
240 }
241 
242 
243 /* Bad class test */
244 ATF_TC(badclass);
245 ATF_TC_HEAD(badclass, tc) {
246 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns "
247 				       "DNS_R_BADCLASS when record class "
248 				       "doesn't match zone class");
249 }
250 ATF_TC_BODY(badclass, tc) {
251 	isc_result_t result;
252 
253 	UNUSED(tc);
254 
255 	result = dns_test_begin(NULL, ISC_FALSE);
256 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
257 
258 	result = test_master("testdata/master/master5.data",
259 			     dns_masterformat_text, NULL, NULL);
260 	ATF_REQUIRE_EQ(result, DNS_R_BADCLASS);
261 
262 	dns_test_end();
263 }
264 
265 /* Too big rdata test */
266 ATF_TC(toobig);
267 ATF_TC_HEAD(toobig, tc) {
268 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns "
269 				       "ISC_R_NOSPACE when record is too big");
270 }
271 ATF_TC_BODY(toobig, tc) {
272 	isc_result_t result;
273 
274 	UNUSED(tc);
275 
276 	result = dns_test_begin(NULL, ISC_FALSE);
277 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
278 
279 	result = test_master("testdata/master/master15.data",
280 			     dns_masterformat_text, NULL, NULL);
281 	ATF_REQUIRE_EQ(result, ISC_R_NOSPACE);
282 
283 	dns_test_end();
284 }
285 
286 /* Maximum rdata test */
287 ATF_TC(maxrdata);
288 ATF_TC_HEAD(maxrdata, tc) {
289 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns "
290 				       "ISC_R_SUCCESS when record is maximum "
291 				       "size");
292 }
293 ATF_TC_BODY(maxrdata, tc) {
294 	isc_result_t result;
295 
296 	UNUSED(tc);
297 
298 	result = dns_test_begin(NULL, ISC_FALSE);
299 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
300 
301 	result = test_master("testdata/master/master16.data",
302 			     dns_masterformat_text, NULL, NULL);
303 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
304 
305 	dns_test_end();
306 }
307 
308 /* DNSKEY test */
309 ATF_TC(dnskey);
310 ATF_TC_HEAD(dnskey, tc) {
311 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands "
312 				       "DNSKEY with key material");
313 }
314 ATF_TC_BODY(dnskey, tc) {
315 	isc_result_t result;
316 
317 	UNUSED(tc);
318 
319 	result = dns_test_begin(NULL, ISC_FALSE);
320 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
321 
322 	result = test_master("testdata/master/master6.data",
323 			     dns_masterformat_text, NULL, NULL);
324 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
325 
326 	dns_test_end();
327 }
328 
329 
330 /* DNSKEY with no key material test */
331 ATF_TC(dnsnokey);
332 ATF_TC_HEAD(dnsnokey, tc) {
333 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands "
334 				       "DNSKEY with no key material");
335 }
336 ATF_TC_BODY(dnsnokey, tc) {
337 	isc_result_t result;
338 
339 	UNUSED(tc);
340 
341 	result = dns_test_begin(NULL, ISC_FALSE);
342 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
343 
344 	result = test_master("testdata/master/master7.data",
345 			     dns_masterformat_text, NULL, NULL);
346 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
347 
348 	dns_test_end();
349 }
350 
351 /* Include test */
352 ATF_TC(include);
353 ATF_TC_HEAD(include, tc) {
354 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands "
355 				       "$INCLUDE");
356 }
357 ATF_TC_BODY(include, tc) {
358 	isc_result_t result;
359 
360 	UNUSED(tc);
361 
362 	result = dns_test_begin(NULL, ISC_FALSE);
363 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
364 
365 	result = test_master("testdata/master/master8.data",
366 			     dns_masterformat_text, NULL, NULL);
367 	ATF_REQUIRE_EQ(result, DNS_R_SEENINCLUDE);
368 
369 	dns_test_end();
370 }
371 
372 /* Include file list test */
373 ATF_TC(master_includelist);
374 ATF_TC_HEAD(master_includelist, tc) {
375 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile4() returns "
376 				       "names of included file");
377 }
378 ATF_TC_BODY(master_includelist, tc) {
379 	isc_result_t result;
380 	char *filename = NULL;
381 
382 	UNUSED(tc);
383 
384 	result = dns_test_begin(NULL, ISC_FALSE);
385 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
386 
387 	result = setup_master(NULL, NULL);
388 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
389 
390 	result = dns_master_loadfile4("testdata/master/master8.data",
391 				      &dns_origin, &dns_origin,
392 				      dns_rdataclass_in, 0, ISC_TRUE,
393 				      &callbacks, include_callback,
394 				      &filename, mctx, dns_masterformat_text);
395 	ATF_CHECK_EQ(result, DNS_R_SEENINCLUDE);
396 	ATF_CHECK(filename != NULL);
397 	if (filename != NULL) {
398 		ATF_CHECK_STREQ(filename, "testdata/master/master7.data");
399 		isc_mem_free(mctx, filename);
400 	}
401 
402 	dns_test_end();
403 }
404 
405 /* Include failure test */
406 ATF_TC(includefail);
407 ATF_TC_HEAD(includefail, tc) {
408 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands "
409 				       "$INCLUDE failures");
410 }
411 ATF_TC_BODY(includefail, tc) {
412 	isc_result_t result;
413 
414 	UNUSED(tc);
415 
416 	result = dns_test_begin(NULL, ISC_FALSE);
417 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
418 
419 	result = test_master("testdata/master/master9.data",
420 			     dns_masterformat_text, NULL, NULL);
421 	ATF_REQUIRE_EQ(result, DNS_R_BADCLASS);
422 
423 	dns_test_end();
424 }
425 
426 
427 /* Non-empty blank lines test */
428 ATF_TC(blanklines);
429 ATF_TC_HEAD(blanklines, tc) {
430 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() handles "
431 				       "non-empty blank lines");
432 }
433 ATF_TC_BODY(blanklines, tc) {
434 	isc_result_t result;
435 
436 	UNUSED(tc);
437 
438 	result = dns_test_begin(NULL, ISC_FALSE);
439 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
440 
441 	result = test_master("testdata/master/master10.data",
442 			     dns_masterformat_text, NULL, NULL);
443 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
444 
445 	dns_test_end();
446 }
447 
448 /* SOA leading zeroes test */
449 ATF_TC(leadingzero);
450 ATF_TC_HEAD(leadingzero, tc) {
451 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() allows "
452 				       "leading zeroes in SOA");
453 }
454 ATF_TC_BODY(leadingzero, tc) {
455 	isc_result_t result;
456 
457 	UNUSED(tc);
458 
459 	result = dns_test_begin(NULL, ISC_FALSE);
460 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
461 
462 	result = test_master("testdata/master/master11.data",
463 			     dns_masterformat_text, NULL, NULL);
464 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
465 
466 	dns_test_end();
467 }
468 
469 ATF_TC(totext);
470 ATF_TC_HEAD(totext, tc) {
471 	atf_tc_set_md_var(tc, "descr", "masterfile totext tests");
472 }
473 ATF_TC_BODY(totext, tc) {
474 	isc_result_t result;
475 	dns_rdataset_t rdataset;
476 	dns_rdatalist_t rdatalist;
477 	isc_buffer_t target;
478 	unsigned char buf[BIGBUFLEN];
479 
480 	UNUSED(tc);
481 
482 	result = dns_test_begin(NULL, ISC_FALSE);
483 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
484 
485 	/* First, test with an empty rdataset */
486 	rdatalist.rdclass = dns_rdataclass_in;
487 	rdatalist.type = dns_rdatatype_none;
488 	rdatalist.covers = dns_rdatatype_none;
489 	rdatalist.ttl = 0;
490 	ISC_LIST_INIT(rdatalist.rdata);
491 	ISC_LINK_INIT(&rdatalist, link);
492 
493 	dns_rdataset_init(&rdataset);
494 	result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
495 	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
496 
497 	isc_buffer_init(&target, buf, BIGBUFLEN);
498 	result = dns_master_rdatasettotext(dns_rootname,
499 					   &rdataset, &dns_master_style_debug,
500 					   &target);
501 	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
502 	ATF_CHECK_EQ(isc_buffer_usedlength(&target), 0);
503 
504 	/*
505 	 * XXX: We will also need to add tests for dumping various
506 	 * rdata types, classes, etc, and comparing the results against
507 	 * known-good output.
508 	 */
509 
510 	dns_test_end();
511 }
512 
513 /* Raw load */
514 ATF_TC(loadraw);
515 ATF_TC_HEAD(loadraw, tc) {
516 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a "
517 				       "valid raw file and returns success");
518 }
519 ATF_TC_BODY(loadraw, tc) {
520 	isc_result_t result;
521 
522 	UNUSED(tc);
523 
524 	result = dns_test_begin(NULL, ISC_FALSE);
525 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
526 
527 	/* Raw format version 0 */
528 	result = test_master("testdata/master/master12.data",
529 			     dns_masterformat_raw, NULL, NULL);
530 	ATF_CHECK_STREQ(isc_result_totext(result), "success");
531 	ATF_CHECK(headerset);
532 	ATF_CHECK_EQ(header.flags, 0);
533 
534 	/* Raw format version 1, no source serial  */
535 	result = test_master("testdata/master/master13.data",
536 			     dns_masterformat_raw, NULL, NULL);
537 	ATF_CHECK_STREQ(isc_result_totext(result), "success");
538 	ATF_CHECK(headerset);
539 	ATF_CHECK_EQ(header.flags, 0);
540 
541 	/* Raw format version 1, source serial == 2011120101 */
542 	result = test_master("testdata/master/master14.data",
543 			     dns_masterformat_raw, NULL, NULL);
544 	ATF_CHECK_STREQ(isc_result_totext(result), "success");
545 	ATF_CHECK(headerset);
546 	ATF_CHECK((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0);
547 	ATF_CHECK_EQ(header.sourceserial, 2011120101);
548 
549 	dns_test_end();
550 }
551 
552 /* Raw dump*/
553 ATF_TC(dumpraw);
554 ATF_TC_HEAD(dumpraw, tc) {
555 	atf_tc_set_md_var(tc, "descr", "dns_master_dump*() functions "
556 				       "dump valid raw files");
557 }
558 ATF_TC_BODY(dumpraw, tc) {
559 	isc_result_t result;
560 	dns_db_t *db = NULL;
561 	dns_dbversion_t *version = NULL;
562 	char myorigin[sizeof(TEST_ORIGIN)];
563 	dns_name_t dnsorigin;
564 	isc_buffer_t source, target;
565 	unsigned char namebuf[BUFLEN];
566 	int len;
567 
568 	UNUSED(tc);
569 
570 	strcpy(myorigin, TEST_ORIGIN);
571 	len = strlen(myorigin);
572 	isc_buffer_init(&source, myorigin, len);
573 	isc_buffer_add(&source, len);
574 	isc_buffer_setactive(&source, len);
575 	isc_buffer_init(&target, namebuf, BUFLEN);
576 	dns_name_init(&dnsorigin, NULL);
577 	result = dns_name_fromtext(&dnsorigin, &source, dns_rootname,
578 				   0, &target);
579 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
580 
581 	result = dns_test_begin(NULL, ISC_FALSE);
582 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
583 
584 	result = dns_db_create(mctx, "rbt", &dnsorigin, dns_dbtype_zone,
585 			       dns_rdataclass_in, 0, NULL, &db);
586 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
587 
588 	result = dns_db_load(db, "testdata/master/master1.data");
589 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
590 
591 	dns_db_currentversion(db, &version);
592 
593 	result = dns_master_dump2(mctx, db, version,
594 				  &dns_master_style_default, "test.dump",
595 				  dns_masterformat_raw);
596 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
597 
598 	result = test_master("test.dump", dns_masterformat_raw, NULL, NULL);
599 	ATF_CHECK_STREQ(isc_result_totext(result), "success");
600 	ATF_CHECK(headerset);
601 	ATF_CHECK_EQ(header.flags, 0);
602 
603 	dns_master_initrawheader(&header);
604 	header.sourceserial = 12345;
605 	header.flags |= DNS_MASTERRAW_SOURCESERIALSET;
606 
607 	unlink("test.dump");
608 	result = dns_master_dump3(mctx, db, version,
609 				  &dns_master_style_default, "test.dump",
610 				  dns_masterformat_raw, &header);
611 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
612 
613 	result = test_master("test.dump", dns_masterformat_raw, NULL, NULL);
614 	ATF_CHECK_STREQ(isc_result_totext(result), "success");
615 	ATF_CHECK(headerset);
616 	ATF_CHECK((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0);
617 	ATF_CHECK_EQ(header.sourceserial, 12345);
618 
619 	unlink("test.dump");
620 	dns_db_closeversion(db, &version, ISC_FALSE);
621 	dns_db_detach(&db);
622 	dns_test_end();
623 }
624 
625 static const char *warn_expect_value;
626 static isc_boolean_t warn_expect_result;
627 
628 static void
629 warn_expect(struct dns_rdatacallbacks *mycallbacks, const char *fmt, ...) {
630 	char buf[4096];
631 	va_list ap;
632 
633 	UNUSED(mycallbacks);
634 
635 	va_start(ap, fmt);
636 	vsnprintf(buf, sizeof(buf), fmt, ap);
637 	va_end(ap);
638 	if (warn_expect_value != NULL && strstr(buf, warn_expect_value) != NULL)
639 		warn_expect_result = ISC_TRUE;
640 }
641 
642 /* Origin change test */
643 ATF_TC(neworigin);
644 ATF_TC_HEAD(neworigin, tc) {
645 	atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() rejects "
646 				       "zones with inherited name following "
647 				       "$ORIGIN");
648 }
649 ATF_TC_BODY(neworigin, tc) {
650 	isc_result_t result;
651 
652 	UNUSED(tc);
653 
654 	result = dns_test_begin(NULL, ISC_FALSE);
655 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
656 
657 	warn_expect_value = "record with inherited owner";
658 	warn_expect_result = ISC_FALSE;
659 	result = test_master("testdata/master/master17.data",
660 			     dns_masterformat_text, warn_expect, NULL);
661 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
662 	ATF_CHECK_MSG(warn_expect_result, "'%s' warning not emitted",
663 		      warn_expect_value);
664 
665 	dns_test_end();
666 }
667 
668 /*
669  * Main
670  */
671 ATF_TP_ADD_TCS(tp) {
672 	ATF_TP_ADD_TC(tp, load);
673 	ATF_TP_ADD_TC(tp, unexpected);
674 	ATF_TP_ADD_TC(tp, noowner);
675 	ATF_TP_ADD_TC(tp, nottl);
676 	ATF_TP_ADD_TC(tp, badclass);
677 	ATF_TP_ADD_TC(tp, dnskey);
678 	ATF_TP_ADD_TC(tp, dnsnokey);
679 	ATF_TP_ADD_TC(tp, include);
680 	ATF_TP_ADD_TC(tp, master_includelist);
681 	ATF_TP_ADD_TC(tp, includefail);
682 	ATF_TP_ADD_TC(tp, blanklines);
683 	ATF_TP_ADD_TC(tp, leadingzero);
684 	ATF_TP_ADD_TC(tp, totext);
685 	ATF_TP_ADD_TC(tp, loadraw);
686 	ATF_TP_ADD_TC(tp, dumpraw);
687 	ATF_TP_ADD_TC(tp, toobig);
688 	ATF_TP_ADD_TC(tp, maxrdata);
689 	ATF_TP_ADD_TC(tp, neworigin);
690 
691 	return (atf_no_error());
692 }
693 
694