1 /* $NetBSD: t_api.c,v 1.7 2014/12/10 04:38:02 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007-2010, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: t_api.c,v 1.68 2010/12/21 04:20:23 marka Exp */
42 #include <isc/boolean.h>
43 #include <isc/commandline.h>
44 #include <isc/print.h>
45 #include <isc/string.h>
48 #include <dns/compress.h>
49 #include <dns/result.h>
51 #include "include/tests/t_api.h"
53 static const char *Usage
=
54 "\t-a : run all tests\n"
55 "\t-b <dir> : chdir to dir before running tests"
56 "\t-c <config_file> : use specified config file\n"
57 "\t-d <debug_level> : set debug level to debug_level\n"
58 "\t-h : print test info\n"
59 "\t-u : print usage info\n"
60 "\t-n <test_name> : run specified test name\n"
61 "\t-t <test_number> : run specified test number\n"
62 "\t-x : don't execute tests in a subproc\n"
63 "\t-q <timeout> : use 'timeout' as the timeout value\n";
65 * -a --> run all tests
66 * -b dir --> chdir to dir before running tests
67 * -c config --> use config file 'config'
68 * -d --> turn on api debugging
69 * -h --> print out available test names
70 * -u --> print usage info
71 * -n name --> run test named name
73 * -x --> don't execute testcases in a subproc
74 * -q timeout --> use 'timeout' as the timeout value
77 #define T_MAXTESTS 256 /*% must be 0 mod 8 */
79 #define T_DEFAULT_CONFIG "t_config"
88 static const char * T_config
;
89 static char T_tvec
[T_MAXTESTS
/ 8];
90 static char * T_env
[T_MAXENV
+ 1];
91 static char T_buf
[T_BIGBUF
];
94 static testspec_t T_testlist
[T_MAXTESTS
];
98 t_initconf(const char *path
);
101 t_dumpconf(const char *path
);
104 t_putinfo(const char *key
, const char *info
);
107 t_getdate(char *buf
, size_t buflen
);
118 t_sighandler(int sig
) {
124 main(int argc
, char **argv
)
126 t_main(int argc
, char **argv
)
143 isc_mem_debugging
= ISC_MEM_DEBUGRECORD
;
148 T_timeout
= T_TCTOUT
;
151 * -a option is now default.
153 memset(T_tvec
, 0xff, sizeof(T_tvec
));
158 while ((c
= isc_commandline_parse(argc
, argv
, ":at:c:d:n:huxq:b:"))
162 * Flag all tests to be run.
164 memset(T_tvec
, 0xff, sizeof(T_tvec
));
167 T_dir
= isc_commandline_argument
;
170 tnum
= atoi(isc_commandline_argument
);
171 if ((tnum
> 0) && (tnum
< T_MAXTESTS
)) {
174 * Turn off effect of -a default
175 * and allow multiple -t and -n
178 memset(T_tvec
, 0, sizeof(T_tvec
));
182 * Flag test tnum to be run.
185 T_tvec
[tnum
/ 8] |= (0x01 << (tnum
% 8));
189 T_config
= isc_commandline_argument
;
192 T_debug
= atoi(isc_commandline_argument
);
195 pts
= &T_testlist
[0];
197 while (pts
->pfv
!= NULL
) {
198 if (! strcmp(pts
->func_name
,
199 isc_commandline_argument
)) {
205 T_tvec
[tnum
/8] |= (0x01 << (tnum
%8));
211 if (pts
->pfv
== NULL
) {
212 fprintf(stderr
, "no such test %s\n",
213 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
);
249 if (T_dir
!= NULL
&& chdir(T_dir
) != 0) {
250 fprintf(stderr
, "chdir %s failed\n", T_dir
);
255 * We don't want buffered output.
258 (void)setbuf(stdout
, NULL
);
259 (void)setbuf(stderr
, NULL
);
267 sigfillset(&sa
.sa_mask
);
269 sa
.sa_handler
= t_sighandler
;
270 (void)sigaction(SIGINT
, &sa
, NULL
);
271 (void)sigaction(SIGALRM
, &sa
, NULL
);
275 * Output start stanza to journal.
278 snprintf(T_buf
, sizeof(T_buf
), "%s:", argv
[0]);
280 (void) t_getdate(T_buf
+ len
, T_BIGBUF
- len
);
281 t_putinfo("S", T_buf
);
284 * Setup the test environment using the config file.
287 if (T_config
== NULL
)
288 T_config
= T_DEFAULT_CONFIG
;
290 t_initconf(T_config
);
292 t_dumpconf(T_config
);
295 * Now invoke all the test cases.
299 pts
= &T_testlist
[0];
300 while (*pts
->pfv
!= NULL
) {
301 if (T_tvec
[tnum
/ 8] & (0x01 << (tnum
% 8))) {
308 } else if (T_pid
> 0) {
311 sa
.sa_handler
= t_sighandler
;
312 (void)sigaction(SIGALRM
, &sa
, NULL
);
315 deadpid
= (pid_t
) -1;
316 while (deadpid
!= T_pid
) {
318 waitpid(T_pid
, &status
, 0);
319 if (deadpid
== T_pid
) {
320 if (WIFSIGNALED(status
)) {
321 if (WTERMSIG(status
) ==
324 "the test case timed out\n");
327 "the test case caused exception %d\n",
329 t_result(T_UNRESOLVED
);
331 } else if ((deadpid
== -1) &&
334 kill(T_pid
, SIGTERM
);
337 else if ((deadpid
== -1) &&
338 ((errno
== ECHILD
) ||
344 sa
.sa_handler
= SIG_IGN
;
345 (void)sigaction(SIGALRM
, &sa
, NULL
);
347 t_info("fork failed, errno == %d\n",
349 t_result(T_UNRESOLVED
);
363 snprintf(T_buf
, sizeof(T_buf
), "%s:", argv
[0]);
365 (void) t_getdate(T_buf
+ len
, T_BIGBUF
- len
);
366 t_putinfo("E", T_buf
);
372 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(buf
, sizeof(buf
), what
, args
);
386 (void)t_putinfo("A", buf
);
391 t_info(const char *format
, ...) {
395 va_start(args
, format
);
396 (void) vsnprintf(buf
, sizeof(buf
), format
, args
);
398 (void) t_putinfo("I", buf
);
402 t_result(int result
) {
435 t_getenv(const char *name
) {
447 if (strncmp(*p
, name
, len
) == 0) {
448 if ( *(*p
+ len
) == '=') {
461 * Read in the config file at path, initializing T_env.
463 * note: no format checking for now ...
468 t_initconf(const char *path
) {
477 fp
= fopen(path
, "r");
481 while (n
< T_MAXENV
) {
485 if ((**p
== '#') || (strchr(*p
, '=') == NULL
)) {
487 * Skip comments and other junk.
503 * Dump T_env to stdout.
508 t_dumpconf(const char *path
) {
514 fp
= fopen(path
, "r");
518 printf("C:%s\n", *p
);
529 * Read a newline or EOF terminated string from fp.
531 * return a malloc'd buf containing the string with
532 * the newline converted to a '\0'.
536 * Caller is responsible for freeing buf.
550 old
= buf
= (char *) malloc(T_BUFSIZ
* sizeof(char));
554 while ((c
= fgetc(fp
)) != EOF
) {
556 if ((c
== '\r') || (c
== '\n'))
563 buf
= (char *)realloc(buf
,
564 size
* sizeof(char));
572 if (c
== EOF
&& n
== 0U) {
581 fprintf(stderr
, "malloc/realloc failed %d", errno
);
588 * Put info to log, using key.
589 * For now, just dump it out.
590 * Later format into pretty lines.
595 t_putinfo(const char *key
, const char *info
) {
601 rval
= printf("%s:%s", key
, info
);
606 t_getdate(char *buf
, size_t buflen
) {
613 n
= strftime(buf
, buflen
- 1, "%A %d %B %H:%M:%S %Y\n", p
);
614 return(n
!= 0U ? buf
: NULL
);
618 * Some generally used utilities.
620 struct dns_errormap
{
624 { ISC_R_SUCCESS
, "ISC_R_SUCCESS" },
625 { ISC_R_EXISTS
, "ISC_R_EXISTS" },
626 { ISC_R_NOTFOUND
, "ISC_R_NOTFOUND" },
627 { ISC_R_NOSPACE
, "ISC_R_NOSPACE" },
628 { ISC_R_UNEXPECTED
, "ISC_R_UNEXPECTED" },
629 { ISC_R_UNEXPECTEDEND
, "ISC_R_UNEXPECTEDEND" },
630 { ISC_R_RANGE
, "ISC_R_RANGE" },
631 { DNS_R_LABELTOOLONG
, "DNS_R_LABELTOOLONG" },
632 { DNS_R_BADESCAPE
, "DNS_R_BADESCAPE" },
633 /* { DNS_R_BADBITSTRING, "DNS_R_BADBITSTRING" }, */
634 /* { DNS_R_BITSTRINGTOOLONG, "DNS_R_BITSTRINGTOOLONG"}, */
635 { DNS_R_EMPTYLABEL
, "DNS_R_EMPTYLABEL" },
636 { DNS_R_BADDOTTEDQUAD
, "DNS_R_BADDOTTEDQUAD" },
637 { DNS_R_UNKNOWN
, "DNS_R_UNKNOWN" },
638 { DNS_R_BADLABELTYPE
, "DNS_R_BADLABELTYPE" },
639 { DNS_R_BADPOINTER
, "DNS_R_BADPOINTER" },
640 { DNS_R_TOOMANYHOPS
, "DNS_R_TOOMANYHOPS" },
641 { DNS_R_DISALLOWED
, "DNS_R_DISALLOWED" },
642 { DNS_R_EXTRATOKEN
, "DNS_R_EXTRATOKEN" },
643 { DNS_R_EXTRADATA
, "DNS_R_EXTRADATA" },
644 { DNS_R_TEXTTOOLONG
, "DNS_R_TEXTTOOLONG" },
645 { DNS_R_SYNTAX
, "DNS_R_SYNTAX" },
646 { DNS_R_BADCKSUM
, "DNS_R_BADCKSUM" },
647 { DNS_R_BADAAAA
, "DNS_R_BADAAAA" },
648 { DNS_R_NOOWNER
, "DNS_R_NOOWNER" },
649 { DNS_R_NOTTL
, "DNS_R_NOTTL" },
650 { DNS_R_BADCLASS
, "DNS_R_BADCLASS" },
651 { DNS_R_PARTIALMATCH
, "DNS_R_PARTIALMATCH" },
652 { DNS_R_NEWORIGIN
, "DNS_R_NEWORIGIN" },
653 { DNS_R_UNCHANGED
, "DNS_R_UNCHANGED" },
654 { DNS_R_BADTTL
, "DNS_R_BADTTL" },
655 { DNS_R_NOREDATA
, "DNS_R_NOREDATA" },
656 { DNS_R_CONTINUE
, "DNS_R_CONTINUE" },
657 { DNS_R_DELEGATION
, "DNS_R_DELEGATION" },
658 { DNS_R_GLUE
, "DNS_R_GLUE" },
659 { DNS_R_DNAME
, "DNS_R_DNAME" },
660 { DNS_R_CNAME
, "DNS_R_CNAME" },
661 { DNS_R_NXDOMAIN
, "DNS_R_NXDOMAIN" },
662 { DNS_R_NXRRSET
, "DNS_R_NXRRSET" },
663 { DNS_R_BADDB
, "DNS_R_BADDB" },
664 { DNS_R_ZONECUT
, "DNS_R_ZONECUT" },
665 { DNS_R_NOTZONETOP
, "DNS_R_NOTZONETOP" },
666 { DNS_R_SEENINCLUDE
, "DNS_R_SEENINCLUDE" },
667 { DNS_R_SINGLETON
, "DNS_R_SINGLETON" },
668 { (isc_result_t
)0, NULL
}
672 t_dns_result_fromtext(char *name
) {
675 struct dns_errormap
*pmap
;
677 result
= ISC_R_UNEXPECTED
;
680 while (pmap
->text
!= NULL
) {
681 if (strcmp(name
, pmap
->text
) == 0)
686 if (pmap
->text
!= NULL
)
687 result
= pmap
->result
;
692 struct dc_method_map
{
693 unsigned int dc_method
;
695 } dc_method_map
[] = {
697 { DNS_COMPRESS_NONE
, "DNS_COMPRESS_NONE" },
698 { DNS_COMPRESS_GLOBAL14
, "DNS_COMPRESS_GLOBAL14" },
699 { DNS_COMPRESS_ALL
, "DNS_COMPRESS_ALL" },
704 t_dc_method_fromtext(char *name
) {
705 unsigned int dc_method
;
706 struct dc_method_map
*pmap
;
708 dc_method
= DNS_COMPRESS_NONE
;
710 pmap
= dc_method_map
;
711 while (pmap
->text
!= NULL
) {
712 if (strcmp(name
, pmap
->text
) == 0)
717 if (pmap
->text
!= NULL
)
718 dc_method
= pmap
->dc_method
;
724 t_bustline(char *line
, char **toks
) {
730 while ((p
= strtok(line
, "\t")) && (cnt
< T_MAXTOKS
)) {
745 pts
= &T_testlist
[0];
747 printf("Available tests:\n");
748 while (pts
->func_name
) {
749 printf("\t%d\t%s\n", cnt
, pts
->func_name
);
757 printf("Usage:\n%s\n", Usage
);
761 t_eval(const char *filename
, int (*func
)(char **), int nargs
) {
771 char *tokens
[T_MAXTOKS
+ 1];
773 tresult
= T_UNTESTED
;
778 fp
= fopen(filename
, "r");
781 while ((p
= t_fgetbs(fp
)) != NULL
) {
786 * Skip comment lines.
788 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
793 cnt
= t_bustline(p
, tokens
);
795 tresult
= func(tokens
);
811 t_info("bad format in %s at line %d\n",
820 t_info("Missing datafile %s\n", filename
);
824 result
= T_UNRESOLVED
;
826 if (nfails
== 0 && nprobs
== 0 && npass
> 0)
838 t_settests(const testspec_t list
[]) {
840 const testspec_t
*pts
;
842 memset(T_testlist
, 0, sizeof(T_testlist
));
845 for (tnum
= 0; tnum
< T_MAXTESTS
- 1; pts
++, tnum
++) {
846 if (*pts
->pfv
== NULL
)
848 T_testlist
[tnum
] = *pts
;