1/* 2 * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19/*! \file */ 20 21#include <config.h> 22 23#include <atf-c.h> 24 25#include <unistd.h> 26 27#include <dns/cache.h> 28#include <dns/callbacks.h> 29#include <dns/master.h> 30#include <dns/masterdump.h> 31#include <dns/name.h> 32#include <dns/rdata.h> 33#include <dns/rdatalist.h> 34#include <dns/rdataset.h> 35 36#include "dnstest.h" 37 38/* 39 * Helper functions 40 */ 41 42#define BUFLEN 255 43#define BIGBUFLEN (64 * 1024) 44#define TEST_ORIGIN "test" 45 46static isc_result_t 47add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset); 48 49static isc_result_t 50add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) { 51 char buf[BIGBUFLEN]; 52 isc_buffer_t target; 53 isc_result_t result; 54 55 UNUSED(arg); 56 57 isc_buffer_init(&target, buf, BIGBUFLEN); 58 result = dns_rdataset_totext(dataset, owner, ISC_FALSE, ISC_FALSE, 59 &target); 60 return(result); 61} 62 63static int 64test_master(const char *testfile) { 65 isc_result_t result; 66 int len; 67 char origin[sizeof(TEST_ORIGIN)]; 68 dns_name_t dns_origin; 69 isc_buffer_t source; 70 isc_buffer_t target; 71 unsigned char name_buf[BUFLEN]; 72 dns_rdatacallbacks_t callbacks; 73 74 strcpy(origin, TEST_ORIGIN); 75 len = strlen(origin); 76 isc_buffer_init(&source, origin, len); 77 isc_buffer_add(&source, len); 78 isc_buffer_setactive(&source, len); 79 isc_buffer_init(&target, name_buf, BUFLEN); 80 dns_name_init(&dns_origin, NULL); 81 82 result = dns_name_fromtext(&dns_origin, &source, dns_rootname, 83 0, &target); 84 if (result != ISC_R_SUCCESS) 85 return(result); 86 87 dns_rdatacallbacks_init_stdio(&callbacks); 88 callbacks.add = add_callback; 89 90 /* 91 * atf-run changes us to a /tmp directory, so tests 92 * that access test data files must first chdir to the proper 93 * location. 94 */ 95 if (chdir(TESTS) == -1) 96 return (ISC_R_FAILURE); 97 98 result = dns_master_loadfile(testfile, &dns_origin, &dns_origin, 99 dns_rdataclass_in, ISC_TRUE, 100 &callbacks, mctx); 101 return (result); 102} 103 104/* 105 * Individual unit tests 106 */ 107 108/* Successful load test */ 109ATF_TC(master_load); 110ATF_TC_HEAD(master_load, tc) { 111 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a " 112 "valid master file and returns success"); 113} 114ATF_TC_BODY(master_load, tc) { 115 isc_result_t result; 116 117 UNUSED(tc); 118 119 result = dns_test_begin(NULL, ISC_FALSE); 120 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 121 122 result = test_master("testdata/master/master1.data"); 123 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 124 125 dns_test_end(); 126} 127 128 129/* Unepxected end of file test */ 130ATF_TC(master_unexpected); 131ATF_TC_HEAD(master_unexpected, tc) { 132 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " 133 "DNS_R_UNEXPECTED when file ends " 134 "too soon"); 135} 136ATF_TC_BODY(master_unexpected, tc) { 137 isc_result_t result; 138 139 UNUSED(tc); 140 141 result = dns_test_begin(NULL, ISC_FALSE); 142 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 143 144 result = test_master("testdata/master/master2.data"); 145 ATF_REQUIRE_EQ(result, ISC_R_UNEXPECTEDEND); 146 147 dns_test_end(); 148} 149 150 151/* No owner test */ 152ATF_TC(master_noowner); 153ATF_TC_HEAD(master_noowner, tc) { 154 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() accepts broken " 155 "zones with no TTL for first record " 156 "if it is an SOA"); 157} 158ATF_TC_BODY(master_noowner, tc) { 159 isc_result_t result; 160 161 UNUSED(tc); 162 163 result = dns_test_begin(NULL, ISC_FALSE); 164 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 165 166 result = test_master("testdata/master/master3.data"); 167 ATF_REQUIRE_EQ(result, DNS_R_NOOWNER); 168 169 dns_test_end(); 170} 171 172 173/* No TTL test */ 174ATF_TC(master_nottl); 175ATF_TC_HEAD(master_nottl, tc) { 176 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " 177 "DNS_R_NOOWNER when no owner name " 178 "is specified"); 179} 180 181ATF_TC_BODY(master_nottl, tc) { 182 isc_result_t result; 183 184 UNUSED(tc); 185 186 result = dns_test_begin(NULL, ISC_FALSE); 187 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 188 189 result = test_master("testdata/master/master4.data"); 190 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 191 192 dns_test_end(); 193} 194 195 196/* Bad class test */ 197ATF_TC(master_badclass); 198ATF_TC_HEAD(master_badclass, tc) { 199 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " 200 "DNS_R_BADCLASS when record class " 201 "doesn't match zone class"); 202} 203ATF_TC_BODY(master_badclass, 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/master5.data"); 212 ATF_REQUIRE_EQ(result, DNS_R_BADCLASS); 213 214 dns_test_end(); 215} 216 217/* DNSKEY test */ 218ATF_TC(master_dnskey); 219ATF_TC_HEAD(master_dnskey, tc) { 220 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " 221 "DNSKEY with key material"); 222} 223ATF_TC_BODY(master_dnskey, tc) { 224 isc_result_t result; 225 226 UNUSED(tc); 227 228 result = dns_test_begin(NULL, ISC_FALSE); 229 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 230 231 result = test_master("testdata/master/master6.data"); 232 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 233 234 dns_test_end(); 235} 236 237 238/* DNSKEY with no key material test */ 239ATF_TC(master_dnsnokey); 240ATF_TC_HEAD(master_dnsnokey, tc) { 241 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " 242 "DNSKEY with no key material"); 243} 244ATF_TC_BODY(master_dnsnokey, tc) { 245 isc_result_t result; 246 247 UNUSED(tc); 248 249 result = dns_test_begin(NULL, ISC_FALSE); 250 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 251 252 result = test_master("testdata/master/master7.data"); 253 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 254 255 dns_test_end(); 256} 257 258/* Include test */ 259ATF_TC(master_include); 260ATF_TC_HEAD(master_include, tc) { 261 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " 262 "$INCLUDE"); 263} 264ATF_TC_BODY(master_include, tc) { 265 isc_result_t result; 266 267 UNUSED(tc); 268 269 result = dns_test_begin(NULL, ISC_FALSE); 270 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 271 272 result = test_master("testdata/master/master8.data"); 273 ATF_REQUIRE_EQ(result, DNS_R_SEENINCLUDE); 274 275 dns_test_end(); 276} 277 278/* Include failure test */ 279ATF_TC(master_includefail); 280ATF_TC_HEAD(master_includefail, tc) { 281 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " 282 "$INCLUDE failures"); 283} 284ATF_TC_BODY(master_includefail, tc) { 285 isc_result_t result; 286 287 UNUSED(tc); 288 289 result = dns_test_begin(NULL, ISC_FALSE); 290 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 291 292 result = test_master("testdata/master/master9.data"); 293 ATF_REQUIRE_EQ(result, DNS_R_BADCLASS); 294 295 dns_test_end(); 296} 297 298 299/* Non-empty blank lines test */ 300ATF_TC(master_blanklines); 301ATF_TC_HEAD(master_blanklines, tc) { 302 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() handles " 303 "non-empty blank lines"); 304} 305ATF_TC_BODY(master_blanklines, tc) { 306 isc_result_t result; 307 308 UNUSED(tc); 309 310 result = dns_test_begin(NULL, ISC_FALSE); 311 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 312 313 result = test_master("testdata/master/master10.data"); 314 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 315 316 dns_test_end(); 317} 318 319/* SOA leading zeroes test */ 320ATF_TC(master_leadingzero); 321ATF_TC_HEAD(master_leadingzero, tc) { 322 atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() allows " 323 "leading zeroes in SOA"); 324} 325ATF_TC_BODY(master_leadingzero, tc) { 326 isc_result_t result; 327 328 UNUSED(tc); 329 330 result = dns_test_begin(NULL, ISC_FALSE); 331 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 332 333 result = test_master("testdata/master/master11.data"); 334 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 335 336 dns_test_end(); 337} 338 339ATF_TC(master_totext); 340ATF_TC_HEAD(master_totext, tc) { 341 atf_tc_set_md_var(tc, "descr", "masterfile totext tests"); 342} 343ATF_TC_BODY(master_totext, tc) { 344 isc_result_t result; 345 dns_rdataset_t rdataset; 346 dns_rdatalist_t rdatalist; 347 isc_buffer_t target; 348 unsigned char buf[BIGBUFLEN]; 349 350 UNUSED(tc); 351 352 result = dns_test_begin(NULL, ISC_FALSE); 353 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); 354 355 /* First, test with an empty rdataset */ 356 rdatalist.rdclass = dns_rdataclass_in; 357 rdatalist.type = dns_rdatatype_none; 358 rdatalist.covers = dns_rdatatype_none; 359 rdatalist.ttl = 0; 360 ISC_LIST_INIT(rdatalist.rdata); 361 ISC_LINK_INIT(&rdatalist, link); 362 363 dns_rdataset_init(&rdataset); 364 result = dns_rdatalist_tordataset(&rdatalist, &rdataset); 365 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 366 367 isc_buffer_init(&target, buf, BIGBUFLEN); 368 result = dns_master_rdatasettotext(dns_rootname, 369 &rdataset, &dns_master_style_debug, 370 &target); 371 ATF_CHECK_EQ(result, ISC_R_SUCCESS); 372 ATF_CHECK_EQ(isc_buffer_usedlength(&target), 0); 373 374 /* 375 * XXX: We will also need to add tests for dumping various 376 * rdata types, classes, etc, and comparing the results against 377 * known-good output. 378 */ 379 380 dns_test_end(); 381} 382 383/* 384 * Main 385 */ 386ATF_TP_ADD_TCS(tp) { 387 ATF_TP_ADD_TC(tp, master_load); 388 ATF_TP_ADD_TC(tp, master_unexpected); 389 ATF_TP_ADD_TC(tp, master_noowner); 390 ATF_TP_ADD_TC(tp, master_nottl); 391 ATF_TP_ADD_TC(tp, master_badclass); 392 ATF_TP_ADD_TC(tp, master_dnskey); 393 ATF_TP_ADD_TC(tp, master_dnsnokey); 394 ATF_TP_ADD_TC(tp, master_include); 395 ATF_TP_ADD_TC(tp, master_includefail); 396 ATF_TP_ADD_TC(tp, master_blanklines); 397 ATF_TP_ADD_TC(tp, master_leadingzero); 398 ATF_TP_ADD_TC(tp, master_totext); 399 400 return (atf_no_error()); 401} 402 403