1 /* $NetBSD: t_api.c,v 1.1.1.3 2014/07/12 11:58:01 spz Exp $ */
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 */
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
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
47 #include <isc/boolean.h>
48 #include <isc/commandline.h>
49 #include <isc/print.h>
50 #include <isc/string.h>
54 #include <dns/compress.h>
55 #include <omapip/result.h>
56 #endif /* DNS_SUPPORT */
59 #define isc_commandline_parse getopt
60 #define isc_commandline_argument optarg
61 #define isc_commandline_option optopt
62 #endif /* BIND_SUPPORT */
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";
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
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 */
93 #define T_DEFAULT_CONFIG "t_config"
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
];
109 t_initconf(const char *path
);
112 t_dumpconf(const char *path
);
115 t_putinfo(const char *key
, const char *info
);
118 t_getdate(char *buf
, size_t buflen
);
129 t_sighandler(int sig
) {
134 main(int argc
, char **argv
) {
146 isc_mem_debugging
= ISC_MEM_DEBUGRECORD
;
147 #endif /* BIND_SUPPORT */
150 T_timeout
= T_TCTOUT
;
153 * -a option is now default.
155 memset(T_tvec
, 0xffff, sizeof(T_tvec
));
160 while ((c
= isc_commandline_parse(argc
, argv
, ":at:c:d:n:huxq:b:"))
164 * Flag all tests to be run.
166 memset(T_tvec
, 0xffff, sizeof(T_tvec
));
169 T_dir
= isc_commandline_argument
;
172 tnum
= atoi(isc_commandline_argument
);
173 if ((tnum
> 0) && (tnum
< T_MAXTESTS
)) {
176 * Turn off effect of -a default
177 * and allow multiple -t and -n
180 memset(T_tvec
, 0, sizeof(T_tvec
));
184 * Flag test tnum to be run.
187 T_tvec
[tnum
/ 8] |= (0x01 << (tnum
% 8));
191 T_config
= isc_commandline_argument
;
194 T_debug
= atoi(isc_commandline_argument
);
197 pts
= &T_testlist
[0];
199 while (pts
->pfv
!= NULL
) {
200 if (! strcmp(pts
->func_name
,
201 isc_commandline_argument
)) {
207 T_tvec
[tnum
/8] |= (0x01 << (tnum
%8));
213 if (pts
->pfv
== NULL
) {
214 fprintf(stderr
, "no such test %s\n",
215 isc_commandline_argument
);
231 T_timeout
= atoi(isc_commandline_argument
);
234 fprintf(stderr
, "Option -%c requires an argument\n",
235 isc_commandline_option
);
239 fprintf(stderr
, "Unrecognized option -%c\n",
240 isc_commandline_option
);
250 IGNORE_RET (chdir(T_dir
));
253 * We don't want buffered output.
256 (void)setbuf(stdout
, NULL
);
257 (void)setbuf(stderr
, NULL
);
264 sigfillset(&sa
.sa_mask
);
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
);
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]);
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
);
297 t_dumpconf(T_config
);
300 * Now invoke all the test cases.
304 pts
= &T_testlist
[0];
305 while (*pts
->pfv
!= NULL
) {
306 if (T_tvec
[tnum
/ 8] & (0x01 << (tnum
% 8))) {
312 } else if (T_pid
> 0) {
315 sa
.sa_handler
= t_sighandler
;
316 (void)sigaction(SIGALRM
, &sa
, NULL
);
319 deadpid
= (pid_t
) -1;
320 while (deadpid
!= T_pid
) {
322 waitpid(T_pid
, &status
, 0);
323 if (deadpid
== T_pid
) {
324 if (WIFSIGNALED(status
)) {
325 if (WTERMSIG(status
) ==
328 "the test case timed out\n");
331 "the test case caused exception %d\n",
333 t_result(T_UNRESOLVED
);
335 } else if ((deadpid
== -1) &&
338 kill(T_pid
, SIGTERM
);
341 else if ((deadpid
== -1) &&
342 ((errno
== ECHILD
) ||
348 sa
.sa_handler
= SIG_IGN
;
349 (void)sigaction(SIGALRM
, &sa
, NULL
);
351 t_info("fork failed, errno == %d\n",
353 t_result(T_UNRESOLVED
);
364 snprintf(T_buf
, sizeof(T_buf
), "%s:", argv
[0]);
366 (void) t_getdate(T_buf
+ len
, T_BIGBUF
- len
);
367 t_putinfo("E", T_buf
);
373 t_assert(const char *component
, int anum
, int class, const char *what
, ...) {
376 (void)printf("T:%s:%d:%s\n", component
, anum
, class == T_REQUIRED
?
380 * Format text to a buffer.
382 va_start(args
, what
);
383 (void)vsnprintf(T_buf
, sizeof(T_buf
), what
, args
);
386 (void)t_putinfo("A", T_buf
);
391 t_info(const char *format
, ...) {
394 va_start(args
, format
);
395 (void) vsnprintf(T_buf
, sizeof(T_buf
), format
, args
);
397 (void) t_putinfo("I", T_buf
);
401 t_result(int result
) {
431 t_getenv(const char *name
) {
443 if (strncmp(*p
, name
, len
) == 0) {
444 if ( *(*p
+ len
) == '=') {
457 * Read in the config file at path, initializing T_env.
459 * note: no format checking for now ...
464 t_initconf(const char *path
) {
473 fp
= fopen(path
, "r");
477 while (n
< T_MAXENV
) {
481 if ((**p
== '#') || (strchr(*p
, '=') == NULL
)) {
483 * Skip comments and other junk.
499 * Dump T_env to stdout.
504 t_dumpconf(const char *path
) {
510 fp
= fopen(path
, "r");
514 printf("C:%s\n", *p
);
525 * Read a newline or EOF terminated string from fp.
527 * return a malloc'd buf containing the string with
528 * the newline converted to a '\0'.
532 * Caller is responsible for freeing buf.
546 old
= buf
= (char *) malloc(T_BUFSIZ
* sizeof(char));
550 while ((c
= fgetc(fp
)) != EOF
) {
559 buf
= (char *)realloc(buf
,
560 size
* sizeof(char));
568 if (c
== EOF
&& n
== 0U) {
577 fprintf(stderr
, "malloc/realloc failed %d", errno
);
584 * Put info to log, using key.
585 * For now, just dump it out.
586 * Later format into pretty lines.
591 t_putinfo(const char *key
, const char *info
) {
597 rval
= printf("%s:%s", key
, info
);
602 t_getdate(char *buf
, size_t buflen
) {
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.
617 struct 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
}
669 t_dns_result_fromtext(char *name
) {
672 struct dns_errormap
*pmap
;
674 result
= ISC_R_UNEXPECTED
;
677 while (pmap
->text
!= NULL
) {
678 if (strcmp(name
, pmap
->text
) == 0)
683 if (pmap
->text
!= NULL
)
684 result
= pmap
->result
;
689 struct dc_method_map
{
690 unsigned int dc_method
;
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" },
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)
714 if (pmap
->text
!= NULL
)
715 dc_method
= pmap
->dc_method
;
719 #endif /* DNS_SUPPORT */
722 t_bustline(char *line
, char **toks
) {
728 while ((p
= strtok(line
, "\t")) && (cnt
< T_MAXTOKS
)) {
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
);
755 printf("Usage:\n%s\n", Usage
);
759 t_eval(const char *filename
, int (*func
)(char **), int nargs
) {
768 char *tokens
[T_MAXTOKS
+ 1];
774 fp
= fopen(filename
, "r");
777 while ((p
= t_fgetbs(fp
)) != NULL
) {
782 * Skip comment lines.
784 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
789 cnt
= t_bustline(p
, tokens
);
791 result
= func(tokens
);
806 t_info("bad format in %s at line %d\n",
815 t_info("Missing datafile %s\n", filename
);
819 result
= T_UNRESOLVED
;
821 if (nfails
== 0 && nprobs
== 0 && npass
> 0)