Annotation of src/external/mpl/bind/dist/lib/dns/tests/dnstest.c, Revision 1.1
1.1 ! christos 1: /* $NetBSD$ */
! 2:
! 3: /*
! 4: * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
! 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 http://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: /*! \file */
! 15:
! 16: #include <config.h>
! 17:
! 18: #include <atf-c.h>
! 19:
! 20: #include <stdlib.h>
! 21: #include <time.h>
! 22: #include <unistd.h>
! 23:
! 24: #include <isc/app.h>
! 25: #include <isc/buffer.h>
! 26: #include <isc/entropy.h>
! 27: #include <isc/file.h>
! 28: #include <isc/hash.h>
! 29: #include <isc/hex.h>
! 30: #include <isc/lex.h>
! 31: #include <isc/mem.h>
! 32: #include <isc/os.h>
! 33: #include <isc/print.h>
! 34: #include <isc/string.h>
! 35: #include <isc/socket.h>
! 36: #include <isc/stdio.h>
! 37: #include <isc/task.h>
! 38: #include <isc/timer.h>
! 39: #include <isc/util.h>
! 40:
! 41: #include <dns/db.h>
! 42: #include <dns/fixedname.h>
! 43: #include <dns/log.h>
! 44: #include <dns/name.h>
! 45: #include <dns/result.h>
! 46: #include <dns/view.h>
! 47: #include <dns/zone.h>
! 48:
! 49: #include "dnstest.h"
! 50:
! 51: isc_mem_t *mctx = NULL;
! 52: isc_entropy_t *ectx = NULL;
! 53: isc_log_t *lctx = NULL;
! 54: isc_taskmgr_t *taskmgr = NULL;
! 55: isc_task_t *maintask = NULL;
! 56: isc_timermgr_t *timermgr = NULL;
! 57: isc_socketmgr_t *socketmgr = NULL;
! 58: dns_zonemgr_t *zonemgr = NULL;
! 59: isc_boolean_t app_running = ISC_FALSE;
! 60: int ncpus;
! 61: isc_boolean_t debug_mem_record = ISC_TRUE;
! 62:
! 63: static isc_boolean_t hash_active = ISC_FALSE, dst_active = ISC_FALSE;
! 64:
! 65: /*
! 66: * Logging categories: this needs to match the list in bin/named/log.c.
! 67: */
! 68: static isc_logcategory_t categories[] = {
! 69: { "", 0 },
! 70: { "client", 0 },
! 71: { "network", 0 },
! 72: { "update", 0 },
! 73: { "queries", 0 },
! 74: { "unmatched", 0 },
! 75: { "update-security", 0 },
! 76: { "query-errors", 0 },
! 77: { NULL, 0 }
! 78: };
! 79:
! 80: static void
! 81: cleanup_managers(void) {
! 82: if (app_running)
! 83: isc_app_finish();
! 84: if (socketmgr != NULL)
! 85: isc_socketmgr_destroy(&socketmgr);
! 86: if (maintask != NULL)
! 87: isc_task_destroy(&maintask);
! 88: if (taskmgr != NULL)
! 89: isc_taskmgr_destroy(&taskmgr);
! 90: if (timermgr != NULL)
! 91: isc_timermgr_destroy(&timermgr);
! 92: }
! 93:
! 94: static isc_result_t
! 95: create_managers(void) {
! 96: isc_result_t result;
! 97: #ifdef ISC_PLATFORM_USETHREADS
! 98: ncpus = isc_os_ncpus();
! 99: #else
! 100: ncpus = 1;
! 101: #endif
! 102:
! 103: CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr));
! 104: CHECK(isc_timermgr_create(mctx, &timermgr));
! 105: CHECK(isc_socketmgr_create(mctx, &socketmgr));
! 106: CHECK(isc_task_create(taskmgr, 0, &maintask));
! 107: return (ISC_R_SUCCESS);
! 108:
! 109: cleanup:
! 110: cleanup_managers();
! 111: return (result);
! 112: }
! 113:
! 114: isc_result_t
! 115: dns_test_begin(FILE *logfile, isc_boolean_t start_managers) {
! 116: isc_result_t result;
! 117:
! 118: if (start_managers)
! 119: CHECK(isc_app_start());
! 120: if (debug_mem_record)
! 121: isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
! 122: CHECK(isc_mem_create(0, 0, &mctx));
! 123: CHECK(isc_entropy_create(mctx, &ectx));
! 124:
! 125: CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING));
! 126: dst_active = ISC_TRUE;
! 127:
! 128: CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
! 129: hash_active = ISC_TRUE;
! 130:
! 131: if (logfile != NULL) {
! 132: isc_logdestination_t destination;
! 133: isc_logconfig_t *logconfig = NULL;
! 134:
! 135: CHECK(isc_log_create(mctx, &lctx, &logconfig));
! 136: isc_log_registercategories(lctx, categories);
! 137: isc_log_setcontext(lctx);
! 138: dns_log_init(lctx);
! 139: dns_log_setcontext(lctx);
! 140:
! 141: destination.file.stream = logfile;
! 142: destination.file.name = NULL;
! 143: destination.file.versions = ISC_LOG_ROLLNEVER;
! 144: destination.file.maximum_size = 0;
! 145: CHECK(isc_log_createchannel(logconfig, "stderr",
! 146: ISC_LOG_TOFILEDESC,
! 147: ISC_LOG_DYNAMIC,
! 148: &destination, 0));
! 149: CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL));
! 150: }
! 151:
! 152: dns_result_register();
! 153:
! 154: if (start_managers)
! 155: CHECK(create_managers());
! 156:
! 157: /*
! 158: * atf-run changes us to a /tmp directory, so tests
! 159: * that access test data files must first chdir to the proper
! 160: * location.
! 161: */
! 162: if (chdir(TESTS) == -1)
! 163: CHECK(ISC_R_FAILURE);
! 164:
! 165: return (ISC_R_SUCCESS);
! 166:
! 167: cleanup:
! 168: dns_test_end();
! 169: return (result);
! 170: }
! 171:
! 172: void
! 173: dns_test_end(void) {
! 174: if (hash_active) {
! 175: isc_hash_destroy();
! 176: hash_active = ISC_FALSE;
! 177: }
! 178: if (dst_active) {
! 179: dst_lib_destroy();
! 180: dst_active = ISC_FALSE;
! 181: }
! 182: if (ectx != NULL)
! 183: isc_entropy_detach(&ectx);
! 184:
! 185: cleanup_managers();
! 186:
! 187: if (lctx != NULL)
! 188: isc_log_destroy(&lctx);
! 189:
! 190: if (mctx != NULL)
! 191: isc_mem_destroy(&mctx);
! 192: }
! 193:
! 194: /*
! 195: * Create a view.
! 196: */
! 197: isc_result_t
! 198: dns_test_makeview(const char *name, dns_view_t **viewp) {
! 199: isc_result_t result;
! 200: dns_view_t *view = NULL;
! 201:
! 202: CHECK(dns_view_create(mctx, dns_rdataclass_in, name, &view));
! 203: *viewp = view;
! 204:
! 205: return (ISC_R_SUCCESS);
! 206:
! 207: cleanup:
! 208: if (view != NULL)
! 209: dns_view_detach(&view);
! 210: return (result);
! 211: }
! 212:
! 213: isc_result_t
! 214: dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view,
! 215: isc_boolean_t createview)
! 216: {
! 217: dns_fixedname_t fixed_origin;
! 218: dns_zone_t *zone = NULL;
! 219: isc_result_t result;
! 220: dns_name_t *origin;
! 221:
! 222: REQUIRE(view == NULL || !createview);
! 223:
! 224: /*
! 225: * Create the zone structure.
! 226: */
! 227: result = dns_zone_create(&zone, mctx);
! 228: if (result != ISC_R_SUCCESS) {
! 229: return (result);
! 230: }
! 231:
! 232: /*
! 233: * Set zone type and origin.
! 234: */
! 235: dns_zone_settype(zone, dns_zone_master);
! 236: origin = dns_fixedname_initname(&fixed_origin);
! 237: result = dns_name_fromstring(origin, name, 0, NULL);
! 238: if (result != ISC_R_SUCCESS) {
! 239: goto detach_zone;
! 240: }
! 241: result = dns_zone_setorigin(zone, origin);
! 242: if (result != ISC_R_SUCCESS) {
! 243: goto detach_zone;
! 244: }
! 245:
! 246: /*
! 247: * If requested, create a view.
! 248: */
! 249: if (createview) {
! 250: result = dns_test_makeview("view", &view);
! 251: if (result != ISC_R_SUCCESS) {
! 252: goto detach_zone;
! 253: }
! 254: }
! 255:
! 256: /*
! 257: * If a view was passed as an argument or created above, attach the
! 258: * created zone to it. Otherwise, set the zone's class to IN.
! 259: */
! 260: if (view != NULL) {
! 261: dns_zone_setview(zone, view);
! 262: dns_zone_setclass(zone, view->rdclass);
! 263: dns_view_addzone(view, zone);
! 264: } else {
! 265: dns_zone_setclass(zone, dns_rdataclass_in);
! 266: }
! 267:
! 268: *zonep = zone;
! 269:
! 270: return (ISC_R_SUCCESS);
! 271:
! 272: detach_zone:
! 273: dns_zone_detach(&zone);
! 274:
! 275: return (result);
! 276: }
! 277:
! 278: isc_result_t
! 279: dns_test_setupzonemgr(void) {
! 280: isc_result_t result;
! 281: REQUIRE(zonemgr == NULL);
! 282:
! 283: result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr,
! 284: &zonemgr);
! 285: return (result);
! 286: }
! 287:
! 288: isc_result_t
! 289: dns_test_managezone(dns_zone_t *zone) {
! 290: isc_result_t result;
! 291: REQUIRE(zonemgr != NULL);
! 292:
! 293: result = dns_zonemgr_setsize(zonemgr, 1);
! 294: if (result != ISC_R_SUCCESS)
! 295: return (result);
! 296:
! 297: result = dns_zonemgr_managezone(zonemgr, zone);
! 298: return (result);
! 299: }
! 300:
! 301: void
! 302: dns_test_releasezone(dns_zone_t *zone) {
! 303: REQUIRE(zonemgr != NULL);
! 304: dns_zonemgr_releasezone(zonemgr, zone);
! 305: }
! 306:
! 307: void
! 308: dns_test_closezonemgr(void) {
! 309: REQUIRE(zonemgr != NULL);
! 310:
! 311: dns_zonemgr_shutdown(zonemgr);
! 312: dns_zonemgr_detach(&zonemgr);
! 313: }
! 314:
! 315: /*
! 316: * Sleep for 'usec' microseconds.
! 317: */
! 318: void
! 319: dns_test_nap(isc_uint32_t usec) {
! 320: #ifdef HAVE_NANOSLEEP
! 321: struct timespec ts;
! 322:
! 323: ts.tv_sec = usec / 1000000;
! 324: ts.tv_nsec = (usec % 1000000) * 1000;
! 325: nanosleep(&ts, NULL);
! 326: #elif HAVE_USLEEP
! 327: usleep(usec);
! 328: #else
! 329: /*
! 330: * No fractional-second sleep function is available, so we
! 331: * round up to the nearest second and sleep instead
! 332: */
! 333: sleep((usec / 1000000) + 1);
! 334: #endif
! 335: }
! 336:
! 337: isc_result_t
! 338: dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin,
! 339: const char *testfile)
! 340: {
! 341: isc_result_t result;
! 342: dns_fixedname_t fixed;
! 343: dns_name_t *name;
! 344:
! 345: name = dns_fixedname_initname(&fixed);
! 346:
! 347: result = dns_name_fromstring(name, origin, 0, NULL);
! 348: if (result != ISC_R_SUCCESS)
! 349: return(result);
! 350:
! 351: result = dns_db_create(mctx, "rbt", name, dbtype, dns_rdataclass_in,
! 352: 0, NULL, db);
! 353: if (result != ISC_R_SUCCESS)
! 354: return (result);
! 355:
! 356: result = dns_db_load(*db, testfile);
! 357: return (result);
! 358: }
! 359:
! 360: static int
! 361: fromhex(char c) {
! 362: if (c >= '0' && c <= '9')
! 363: return (c - '0');
! 364: else if (c >= 'a' && c <= 'f')
! 365: return (c - 'a' + 10);
! 366: else if (c >= 'A' && c <= 'F')
! 367: return (c - 'A' + 10);
! 368:
! 369: printf("bad input format: %02x\n", c);
! 370: exit(3);
! 371: /* NOTREACHED */
! 372: }
! 373:
! 374: /*
! 375: * Format contents of given memory region as a hex string, using the buffer
! 376: * of length 'buflen' pointed to by 'buf'. 'buflen' must be at least three
! 377: * times 'len'. Always returns 'buf'.
! 378: */
! 379: char *
! 380: dns_test_tohex(const unsigned char *data, size_t len, char *buf, size_t buflen)
! 381: {
! 382: isc_constregion_t source = {
! 383: .base = data,
! 384: .length = len
! 385: };
! 386: isc_buffer_t target;
! 387: isc_result_t result;
! 388:
! 389: memset(buf, 0, buflen);
! 390: isc_buffer_init(&target, buf, buflen);
! 391: result = isc_hex_totext((isc_region_t *)&source, 1, " ", &target);
! 392: ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
! 393:
! 394: return (buf);
! 395: }
! 396:
! 397: isc_result_t
! 398: dns_test_getdata(const char *file, unsigned char *buf,
! 399: size_t bufsiz, size_t *sizep)
! 400: {
! 401: isc_result_t result;
! 402: unsigned char *bp;
! 403: char *rp, *wp;
! 404: char s[BUFSIZ];
! 405: size_t len, i;
! 406: FILE *f = NULL;
! 407: int n;
! 408:
! 409: result = isc_stdio_open(file, "r", &f);
! 410: if (result != ISC_R_SUCCESS)
! 411: return (result);
! 412:
! 413: bp = buf;
! 414: while (fgets(s, sizeof(s), f) != NULL) {
! 415: rp = s;
! 416: wp = s;
! 417: len = 0;
! 418: while (*rp != '\0') {
! 419: if (*rp == '#')
! 420: break;
! 421: if (*rp != ' ' && *rp != '\t' &&
! 422: *rp != '\r' && *rp != '\n') {
! 423: *wp++ = *rp;
! 424: len++;
! 425: }
! 426: rp++;
! 427: }
! 428: if (len == 0U)
! 429: continue;
! 430: if (len % 2 != 0U)
! 431: CHECK(ISC_R_UNEXPECTEDEND);
! 432: if (len > bufsiz * 2)
! 433: CHECK(ISC_R_NOSPACE);
! 434: rp = s;
! 435: for (i = 0; i < len; i += 2) {
! 436: n = fromhex(*rp++);
! 437: n *= 16;
! 438: n += fromhex(*rp++);
! 439: *bp++ = n;
! 440: }
! 441: }
! 442:
! 443:
! 444: *sizep = bp - buf;
! 445:
! 446: result = ISC_R_SUCCESS;
! 447:
! 448: cleanup:
! 449: isc_stdio_close(f);
! 450: return (result);
! 451: }
! 452:
! 453: isc_result_t
! 454: dns_test_rdatafromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
! 455: dns_rdatatype_t rdtype, unsigned char *dst,
! 456: size_t dstlen, const char *src)
! 457: {
! 458: isc_buffer_t source, target;
! 459: isc_lex_t *lex = NULL;
! 460: isc_result_t result;
! 461: size_t length;
! 462:
! 463: REQUIRE(rdata != NULL);
! 464: REQUIRE(DNS_RDATA_INITIALIZED(rdata));
! 465: REQUIRE(dst != NULL);
! 466: REQUIRE(src != NULL);
! 467:
! 468: /*
! 469: * Set up source to hold the input string.
! 470: */
! 471: length = strlen(src);
! 472: isc_buffer_constinit(&source, src, length);
! 473: isc_buffer_add(&source, length);
! 474:
! 475: /*
! 476: * Create a lexer as one is required by dns_rdata_fromtext().
! 477: */
! 478: result = isc_lex_create(mctx, 64, &lex);
! 479: if (result != ISC_R_SUCCESS) {
! 480: return (result);
! 481: }
! 482:
! 483: /*
! 484: * Point lexer at source.
! 485: */
! 486: result = isc_lex_openbuffer(lex, &source);
! 487: if (result != ISC_R_SUCCESS) {
! 488: goto destroy_lexer;
! 489: }
! 490:
! 491: /*
! 492: * Set up target for storing uncompressed wire form of provided RDATA.
! 493: */
! 494: isc_buffer_init(&target, dst, dstlen);
! 495:
! 496: /*
! 497: * Parse input string, determining result.
! 498: */
! 499: result = dns_rdata_fromtext(rdata, rdclass, rdtype, lex, dns_rootname,
! 500: 0, NULL, &target, NULL);
! 501:
! 502: destroy_lexer:
! 503: isc_lex_destroy(&lex);
! 504:
! 505: return (result);
! 506: }
! 507:
! 508: void
! 509: dns_test_namefromstring(const char *namestr, dns_fixedname_t *fname) {
! 510: size_t length;
! 511: isc_buffer_t *b = NULL;
! 512: isc_result_t result;
! 513: dns_name_t *name;
! 514:
! 515: length = strlen(namestr);
! 516:
! 517: result = isc_buffer_allocate(mctx, &b, length);
! 518: ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
! 519: isc_buffer_putmem(b, (const unsigned char *) namestr, length);
! 520:
! 521: name = dns_fixedname_initname(fname);
! 522: ATF_REQUIRE(name != NULL);
! 523: result = dns_name_fromtext(name, b, dns_rootname, 0, NULL);
! 524: ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
! 525:
! 526: isc_buffer_free(&b);
! 527: }
! 528:
! 529: isc_result_t
! 530: dns_test_difffromchanges(dns_diff_t *diff, const zonechange_t *changes) {
! 531: isc_result_t result = ISC_R_SUCCESS;
! 532: unsigned char rdata_buf[1024];
! 533: dns_difftuple_t *tuple = NULL;
! 534: isc_consttextregion_t region;
! 535: dns_rdatatype_t rdatatype;
! 536: dns_fixedname_t fixedname;
! 537: dns_rdata_t rdata;
! 538: dns_name_t *name;
! 539: size_t i;
! 540:
! 541: REQUIRE(diff != NULL);
! 542: REQUIRE(changes != NULL);
! 543:
! 544: dns_diff_init(mctx, diff);
! 545:
! 546: for (i = 0; changes[i].owner != NULL; i++) {
! 547: /*
! 548: * Parse owner name.
! 549: */
! 550: name = dns_fixedname_initname(&fixedname);
! 551: result = dns_name_fromstring(name, changes[i].owner, 0, mctx);
! 552: if (result != ISC_R_SUCCESS) {
! 553: break;
! 554: }
! 555:
! 556: /*
! 557: * Parse RDATA type.
! 558: */
! 559: region.base = changes[i].type;
! 560: region.length = strlen(changes[i].type);
! 561: result = dns_rdatatype_fromtext(&rdatatype,
! 562: (isc_textregion_t *)®ion);
! 563: if (result != ISC_R_SUCCESS) {
! 564: break;
! 565: }
! 566:
! 567: /*
! 568: * Parse RDATA.
! 569: */
! 570: dns_rdata_init(&rdata);
! 571: result = dns_test_rdatafromstring(&rdata, dns_rdataclass_in,
! 572: rdatatype, rdata_buf,
! 573: sizeof(rdata_buf),
! 574: changes[i].rdata);
! 575: if (result != ISC_R_SUCCESS) {
! 576: break;
! 577: }
! 578:
! 579: /*
! 580: * Create a diff tuple for the parsed change and append it to
! 581: * the diff.
! 582: */
! 583: result = dns_difftuple_create(mctx, changes[i].op, name,
! 584: changes[i].ttl, &rdata, &tuple);
! 585: if (result != ISC_R_SUCCESS) {
! 586: break;
! 587: }
! 588: dns_diff_append(diff, &tuple);
! 589: }
! 590:
! 591: if (result != ISC_R_SUCCESS) {
! 592: dns_diff_clear(diff);
! 593: }
! 594:
! 595: return (result);
! 596: }
CVSweb <webmaster@jp.NetBSD.org>