Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / tests / t_api.c
blob057df180e840089ee1d5482b7148a1b4aeee488f
1 /* $NetBSD: t_api.c,v 1.1.1.3 2014/07/12 11:58:01 spz Exp $ */
2 /*
3 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
4 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
19 /* Id: t_api.c,v 1.4 2009/10/28 04:12:30 sar Exp */
21 /*! \file */
24 * This test API framework is taken from the BIND 9 code. It has been
25 * modified to remove the DNS-specific parts, and the BIND-specific
26 * parts.
28 * The DNS-specific parts are now wrapped with the DNS_SUPPORT macro,
29 * and the BIND-specific parts are now wrapped with the BIND_SUPPORT
30 * macro.
33 #include <config.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <unistd.h>
45 #include <sys/wait.h>
47 #include <isc/boolean.h>
48 #include <isc/commandline.h>
49 #include <isc/print.h>
50 #include <isc/string.h>
51 #include <isc/mem.h>
53 #ifdef DNS_SUPPORT
54 #include <dns/compress.h>
55 #include <omapip/result.h>
56 #endif /* DNS_SUPPORT */
58 #ifndef BIND_SUPPORT
59 #define isc_commandline_parse getopt
60 #define isc_commandline_argument optarg
61 #define isc_commandline_option optopt
62 #endif /* BIND_SUPPORT */
64 #include "t_api.h"
65 #include "cdefs.h"
67 static const char *Usage =
68 "\t-a : run all tests\n"
69 "\t-b <dir> : chdir to dir before running tests"
70 "\t-c <config_file> : use specified config file\n"
71 "\t-d <debug_level> : set debug level to debug_level\n"
72 "\t-h : print test info\n"
73 "\t-u : print usage info\n"
74 "\t-n <test_name> : run specified test name\n"
75 "\t-t <test_number> : run specified test number\n"
76 "\t-x : don't execute tests in a subproc\n"
77 "\t-q <timeout> : use 'timeout' as the timeout value\n";
78 /*!<
79 * -a --> run all tests
80 * -b dir --> chdir to dir before running tests
81 * -c config --> use config file 'config'
82 * -d --> turn on api debugging
83 * -h --> print out available test names
84 * -u --> print usage info
85 * -n name --> run test named name
86 * -tn --> run test n
87 * -x --> don't execute testcases in a subproc
88 * -q timeout --> use 'timeout' as the timeout value
91 #define T_MAXTESTS 256 /*% must be 0 mod 8 */
92 #define T_MAXENV 256
93 #define T_DEFAULT_CONFIG "t_config"
94 #define T_BUFSIZ 256
95 #define T_BIGBUF 4096
97 #define T_TCTOUT 60
99 int T_debug;
100 int T_timeout;
101 pid_t T_pid;
102 static const char * T_config;
103 static char T_tvec[T_MAXTESTS / 8];
104 static char * T_env[T_MAXENV + 1];
105 static char T_buf[T_BIGBUF];
106 static char * T_dir;
108 static int
109 t_initconf(const char *path);
111 static int
112 t_dumpconf(const char *path);
114 static int
115 t_putinfo(const char *key, const char *info);
117 static char *
118 t_getdate(char *buf, size_t buflen);
120 static void
121 printhelp(void);
123 static void
124 printusage(void);
126 static int T_int;
128 static void
129 t_sighandler(int sig) {
130 T_int = sig;
134 main(int argc, char **argv) {
135 int c;
136 int tnum;
137 int subprocs;
138 pid_t deadpid;
139 int status;
140 int len;
141 isc_boolean_t first;
142 testspec_t *pts;
143 struct sigaction sa;
145 #ifdef BIND_SUPPORT
146 isc_mem_debugging = ISC_MEM_DEBUGRECORD;
147 #endif /* BIND_SUPPORT */
148 first = ISC_TRUE;
149 subprocs = 1;
150 T_timeout = T_TCTOUT;
153 * -a option is now default.
155 memset(T_tvec, 0xffff, sizeof(T_tvec));
158 * Parse args.
160 while ((c = isc_commandline_parse(argc, argv, ":at:c:d:n:huxq:b:"))
161 != -1) {
162 if (c == 'a') {
164 * Flag all tests to be run.
166 memset(T_tvec, 0xffff, sizeof(T_tvec));
168 else if (c == 'b') {
169 T_dir = isc_commandline_argument;
171 else if (c == 't') {
172 tnum = atoi(isc_commandline_argument);
173 if ((tnum > 0) && (tnum < T_MAXTESTS)) {
174 if (first) {
176 * Turn off effect of -a default
177 * and allow multiple -t and -n
178 * options.
180 memset(T_tvec, 0, sizeof(T_tvec));
181 first = ISC_FALSE;
184 * Flag test tnum to be run.
186 tnum -= 1;
187 T_tvec[tnum / 8] |= (0x01 << (tnum % 8));
190 else if (c == 'c') {
191 T_config = isc_commandline_argument;
193 else if (c == 'd') {
194 T_debug = atoi(isc_commandline_argument);
196 else if (c == 'n') {
197 pts = &T_testlist[0];
198 tnum = 0;
199 while (pts->pfv != NULL) {
200 if (! strcmp(pts->func_name,
201 isc_commandline_argument)) {
202 if (first) {
203 memset(T_tvec, 0,
204 sizeof(T_tvec));
205 first = ISC_FALSE;
207 T_tvec[tnum/8] |= (0x01 << (tnum%8));
208 break;
210 ++pts;
211 ++tnum;
213 if (pts->pfv == NULL) {
214 fprintf(stderr, "no such test %s\n",
215 isc_commandline_argument);
216 exit(1);
219 else if (c == 'h') {
220 printhelp();
221 exit(0);
223 else if (c == 'u') {
224 printusage();
225 exit(0);
227 else if (c == 'x') {
228 subprocs = 0;
230 else if (c == 'q') {
231 T_timeout = atoi(isc_commandline_argument);
233 else if (c == ':') {
234 fprintf(stderr, "Option -%c requires an argument\n",
235 isc_commandline_option);
236 exit(1);
238 else if (c == '?') {
239 fprintf(stderr, "Unrecognized option -%c\n",
240 isc_commandline_option);
241 exit(1);
246 * Set cwd.
249 if (T_dir != NULL)
250 IGNORE_RET (chdir(T_dir));
253 * We don't want buffered output.
256 (void)setbuf(stdout, NULL);
257 (void)setbuf(stderr, NULL);
260 * Setup signals.
263 sa.sa_flags = 0;
264 sigfillset(&sa.sa_mask);
266 #ifdef SIGCHLD
268 * This is mostly here for NetBSD's pthread implementation, until
269 * people catch up to the latest unproven-pthread package.
271 sa.sa_handler = SIG_DFL;
272 (void)sigaction(SIGCHLD, &sa, NULL);
273 #endif
275 sa.sa_handler = t_sighandler;
276 (void)sigaction(SIGINT, &sa, NULL);
277 (void)sigaction(SIGALRM, &sa, NULL);
280 * Output start stanza to journal.
283 snprintf(T_buf, sizeof(T_buf), "%s:", argv[0]);
284 len = strlen(T_buf);
285 (void) t_getdate(T_buf + len, T_BIGBUF - len);
286 t_putinfo("S", T_buf);
289 * Setup the test environment using the config file.
292 if (T_config == NULL)
293 T_config = T_DEFAULT_CONFIG;
295 t_initconf(T_config);
296 if (T_debug)
297 t_dumpconf(T_config);
300 * Now invoke all the test cases.
303 tnum = 0;
304 pts = &T_testlist[0];
305 while (*pts->pfv != NULL) {
306 if (T_tvec[tnum / 8] & (0x01 << (tnum % 8))) {
307 if (subprocs) {
308 T_pid = fork();
309 if (T_pid == 0) {
310 (*pts->pfv)();
311 exit(0);
312 } else if (T_pid > 0) {
314 T_int = 0;
315 sa.sa_handler = t_sighandler;
316 (void)sigaction(SIGALRM, &sa, NULL);
317 alarm(T_timeout);
319 deadpid = (pid_t) -1;
320 while (deadpid != T_pid) {
321 deadpid =
322 waitpid(T_pid, &status, 0);
323 if (deadpid == T_pid) {
324 if (WIFSIGNALED(status)) {
325 if (WTERMSIG(status) ==
326 SIGTERM)
327 t_info(
328 "the test case timed out\n");
329 else
330 t_info(
331 "the test case caused exception %d\n",
332 WTERMSIG(status));
333 t_result(T_UNRESOLVED);
335 } else if ((deadpid == -1) &&
336 (errno == EINTR) &&
337 T_int) {
338 kill(T_pid, SIGTERM);
339 T_int = 0;
341 else if ((deadpid == -1) &&
342 ((errno == ECHILD) ||
343 (errno == ESRCH)))
344 break;
347 alarm(0);
348 sa.sa_handler = SIG_IGN;
349 (void)sigaction(SIGALRM, &sa, NULL);
350 } else {
351 t_info("fork failed, errno == %d\n",
352 errno);
353 t_result(T_UNRESOLVED);
356 else {
357 (*pts->pfv)();
360 ++pts;
361 ++tnum;
364 snprintf(T_buf, sizeof(T_buf), "%s:", argv[0]);
365 len = strlen(T_buf);
366 (void) t_getdate(T_buf + len, T_BIGBUF - len);
367 t_putinfo("E", T_buf);
369 return(0);
372 void
373 t_assert(const char *component, int anum, int class, const char *what, ...) {
374 va_list args;
376 (void)printf("T:%s:%d:%s\n", component, anum, class == T_REQUIRED ?
377 "A" : "C");
380 * Format text to a buffer.
382 va_start(args, what);
383 (void)vsnprintf(T_buf, sizeof(T_buf), what, args);
384 va_end(args);
386 (void)t_putinfo("A", T_buf);
387 (void)printf("\n");
390 void
391 t_info(const char *format, ...) {
392 va_list args;
394 va_start(args, format);
395 (void) vsnprintf(T_buf, sizeof(T_buf), format, args);
396 va_end(args);
397 (void) t_putinfo("I", T_buf);
400 void
401 t_result(int result) {
402 const char *p;
404 switch (result) {
405 case T_PASS:
406 p = "PASS";
407 break;
408 case T_FAIL:
409 p = "FAIL";
410 break;
411 case T_UNRESOLVED:
412 p = "UNRESOLVED";
413 break;
414 case T_UNSUPPORTED:
415 p = "UNSUPPORTED";
416 break;
417 case T_UNTESTED:
418 p = "UNTESTED";
419 break;
420 case T_THREADONLY:
421 p = "THREADONLY";
422 break;
423 default:
424 p = "UNKNOWN";
425 break;
427 printf("R:%s\n", p);
430 char *
431 t_getenv(const char *name) {
432 char *n;
433 char **p;
434 size_t len;
436 n = NULL;
437 if (name && *name) {
439 p = &T_env[0];
440 len = strlen(name);
442 while (*p != NULL) {
443 if (strncmp(*p, name, len) == 0) {
444 if ( *(*p + len) == '=') {
445 n = *p + len + 1;
446 break;
449 ++p;
452 return(n);
457 * Read in the config file at path, initializing T_env.
459 * note: no format checking for now ...
463 static int
464 t_initconf(const char *path) {
466 int n;
467 int rval;
468 char **p;
469 FILE *fp;
471 rval = -1;
473 fp = fopen(path, "r");
474 if (fp != NULL) {
475 n = 0;
476 p = &T_env[0];
477 while (n < T_MAXENV) {
478 *p = t_fgetbs(fp);
479 if (*p == NULL)
480 break;
481 if ((**p == '#') || (strchr(*p, '=') == NULL)) {
483 * Skip comments and other junk.
485 (void)free(*p);
486 continue;
488 ++p; ++n;
490 (void)fclose(fp);
491 rval = 0;
494 return (rval);
499 * Dump T_env to stdout.
503 static int
504 t_dumpconf(const char *path) {
505 int rval;
506 char **p;
507 FILE *fp;
509 rval = -1;
510 fp = fopen(path, "r");
511 if (fp != NULL) {
512 p = &T_env[0];
513 while (*p != NULL) {
514 printf("C:%s\n", *p);
515 ++p;
517 (void) fclose(fp);
518 rval = 0;
520 return(rval);
525 * Read a newline or EOF terminated string from fp.
526 * On success:
527 * return a malloc'd buf containing the string with
528 * the newline converted to a '\0'.
529 * On error:
530 * return NULL.
532 * Caller is responsible for freeing buf.
536 char *
537 t_fgetbs(FILE *fp) {
538 int c;
539 size_t n;
540 size_t size;
541 char *buf, *old;
542 char *p;
544 n = 0;
545 size = T_BUFSIZ;
546 old = buf = (char *) malloc(T_BUFSIZ * sizeof(char));
548 if (buf != NULL) {
549 p = buf;
550 while ((c = fgetc(fp)) != EOF) {
552 if (c == '\n')
553 break;
555 *p++ = c;
556 ++n;
557 if ( n >= size ) {
558 size += T_BUFSIZ;
559 buf = (char *)realloc(buf,
560 size * sizeof(char));
561 if (buf == NULL)
562 goto err;
563 old = buf;
564 p = buf + n;
567 *p = '\0';
568 if (c == EOF && n == 0U) {
569 free(buf);
570 return (NULL);
572 return (buf);
573 } else {
574 err:
575 if (old != NULL)
576 free(old);
577 fprintf(stderr, "malloc/realloc failed %d", errno);
578 return(NULL);
584 * Put info to log, using key.
585 * For now, just dump it out.
586 * Later format into pretty lines.
590 static int
591 t_putinfo(const char *key, const char *info) {
592 int rval;
595 * For now.
597 rval = printf("%s:%s", key, info);
598 return(rval);
601 static char *
602 t_getdate(char *buf, size_t buflen) {
603 size_t n;
604 time_t t;
605 struct tm *p;
607 t = time(NULL);
608 p = localtime(&t);
609 n = strftime(buf, buflen - 1, "%A %d %B %H:%M:%S %Y\n", p);
610 return(n != 0U ? buf : NULL);
614 * Some generally used utilities.
616 #ifdef DNS_SUPPORT
617 struct dns_errormap {
618 isc_result_t result;
619 const char *text;
620 } dns_errormap[] = {
621 { ISC_R_SUCCESS, "ISC_R_SUCCESS" },
622 { ISC_R_EXISTS, "ISC_R_EXISTS" },
623 { ISC_R_NOTFOUND, "ISC_R_NOTFOUND" },
624 { ISC_R_NOSPACE, "ISC_R_NOSPACE" },
625 { ISC_R_UNEXPECTED, "ISC_R_UNEXPECTED" },
626 { ISC_R_UNEXPECTEDEND, "ISC_R_UNEXPECTEDEND" },
627 { ISC_R_RANGE, "ISC_R_RANGE" },
628 { DNS_R_LABELTOOLONG, "DNS_R_LABELTOOLONG" },
629 { DNS_R_BADESCAPE, "DNS_R_BADESCAPE" },
630 /* { DNS_R_BADBITSTRING, "DNS_R_BADBITSTRING" }, */
631 /* { DNS_R_BITSTRINGTOOLONG, "DNS_R_BITSTRINGTOOLONG"}, */
632 { DNS_R_EMPTYLABEL, "DNS_R_EMPTYLABEL" },
633 { DNS_R_BADDOTTEDQUAD, "DNS_R_BADDOTTEDQUAD" },
634 { DNS_R_UNKNOWN, "DNS_R_UNKNOWN" },
635 { DNS_R_BADLABELTYPE, "DNS_R_BADLABELTYPE" },
636 { DNS_R_BADPOINTER, "DNS_R_BADPOINTER" },
637 { DNS_R_TOOMANYHOPS, "DNS_R_TOOMANYHOPS" },
638 { DNS_R_DISALLOWED, "DNS_R_DISALLOWED" },
639 { DNS_R_EXTRATOKEN, "DNS_R_EXTRATOKEN" },
640 { DNS_R_EXTRADATA, "DNS_R_EXTRADATA" },
641 { DNS_R_TEXTTOOLONG, "DNS_R_TEXTTOOLONG" },
642 { DNS_R_SYNTAX, "DNS_R_SYNTAX" },
643 { DNS_R_BADCKSUM, "DNS_R_BADCKSUM" },
644 { DNS_R_BADAAAA, "DNS_R_BADAAAA" },
645 { DNS_R_NOOWNER, "DNS_R_NOOWNER" },
646 { DNS_R_NOTTL, "DNS_R_NOTTL" },
647 { DNS_R_BADCLASS, "DNS_R_BADCLASS" },
648 { DNS_R_PARTIALMATCH, "DNS_R_PARTIALMATCH" },
649 { DNS_R_NEWORIGIN, "DNS_R_NEWORIGIN" },
650 { DNS_R_UNCHANGED, "DNS_R_UNCHANGED" },
651 { DNS_R_BADTTL, "DNS_R_BADTTL" },
652 { DNS_R_NOREDATA, "DNS_R_NOREDATA" },
653 { DNS_R_CONTINUE, "DNS_R_CONTINUE" },
654 { DNS_R_DELEGATION, "DNS_R_DELEGATION" },
655 { DNS_R_GLUE, "DNS_R_GLUE" },
656 { DNS_R_DNAME, "DNS_R_DNAME" },
657 { DNS_R_CNAME, "DNS_R_CNAME" },
658 { DNS_R_NXDOMAIN, "DNS_R_NXDOMAIN" },
659 { DNS_R_NXRRSET, "DNS_R_NXRRSET" },
660 { DNS_R_BADDB, "DNS_R_BADDB" },
661 { DNS_R_ZONECUT, "DNS_R_ZONECUT" },
662 { DNS_R_NOTZONETOP, "DNS_R_NOTZONETOP" },
663 { DNS_R_SEENINCLUDE, "DNS_R_SEENINCLUDE" },
664 { DNS_R_SINGLETON, "DNS_R_SINGLETON" },
665 { (isc_result_t)0, NULL }
668 isc_result_t
669 t_dns_result_fromtext(char *name) {
671 isc_result_t result;
672 struct dns_errormap *pmap;
674 result = ISC_R_UNEXPECTED;
676 pmap = dns_errormap;
677 while (pmap->text != NULL) {
678 if (strcmp(name, pmap->text) == 0)
679 break;
680 ++pmap;
683 if (pmap->text != NULL)
684 result = pmap->result;
686 return (result);
689 struct dc_method_map {
690 unsigned int dc_method;
691 const char *text;
692 } dc_method_map[] = {
694 { DNS_COMPRESS_NONE, "DNS_COMPRESS_NONE" },
695 { DNS_COMPRESS_GLOBAL14, "DNS_COMPRESS_GLOBAL14" },
696 { DNS_COMPRESS_ALL, "DNS_COMPRESS_ALL" },
697 { 0, NULL }
700 unsigned int
701 t_dc_method_fromtext(char *name) {
702 unsigned int dc_method;
703 struct dc_method_map *pmap;
705 dc_method = DNS_COMPRESS_NONE;
707 pmap = dc_method_map;
708 while (pmap->text != NULL) {
709 if (strcmp(name, pmap->text) == 0)
710 break;
711 ++pmap;
714 if (pmap->text != NULL)
715 dc_method = pmap->dc_method;
717 return(dc_method);
719 #endif /* DNS_SUPPORT */
722 t_bustline(char *line, char **toks) {
723 int cnt;
724 char *p;
726 cnt = 0;
727 if (line && *line) {
728 while ((p = strtok(line, "\t")) && (cnt < T_MAXTOKS)) {
729 *toks++ = p;
730 line = NULL;
731 ++cnt;
734 return(cnt);
737 static void
738 printhelp(void) {
739 int cnt;
740 testspec_t *pts;
742 cnt = 1;
743 pts = &T_testlist[0];
745 printf("Available tests:\n");
746 while (pts->func_name) {
747 printf("\t%d\t%s\n", cnt, pts->func_name);
748 ++pts;
749 ++cnt;
753 static void
754 printusage(void) {
755 printf("Usage:\n%s\n", Usage);
759 t_eval(const char *filename, int (*func)(char **), int nargs) {
760 FILE *fp;
761 char *p;
762 int line;
763 int cnt;
764 int result;
765 int nfails;
766 int nprobs;
767 int npass;
768 char *tokens[T_MAXTOKS + 1];
770 npass = 0;
771 nfails = 0;
772 nprobs = 0;
774 fp = fopen(filename, "r");
775 if (fp != NULL) {
776 line = 0;
777 while ((p = t_fgetbs(fp)) != NULL) {
779 ++line;
782 * Skip comment lines.
784 if ((isspace((unsigned char)*p)) || (*p == '#')) {
785 (void)free(p);
786 continue;
789 cnt = t_bustline(p, tokens);
790 if (cnt == nargs) {
791 result = func(tokens);
792 switch (result) {
793 case T_PASS:
794 ++npass;
795 break;
796 case T_FAIL:
797 ++nfails;
798 break;
799 case T_UNTESTED:
800 break;
801 default:
802 ++nprobs;
803 break;
805 } else {
806 t_info("bad format in %s at line %d\n",
807 filename, line);
808 ++nprobs;
811 (void)free(p);
813 (void)fclose(fp);
814 } else {
815 t_info("Missing datafile %s\n", filename);
816 ++nprobs;
819 result = T_UNRESOLVED;
821 if (nfails == 0 && nprobs == 0 && npass > 0)
822 result = T_PASS;
823 else if (nfails > 0)
824 result = T_FAIL;
825 else if (npass == 0)
826 result = T_UNTESTED;
828 return (result);