]>
git.ipfire.org Git - thirdparty/dhcp.git/blob - tests/t_api.c
2 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: t_api.c,v 1.4 2009/10/28 04:12:30 sar Exp $ */
23 * This test API framework is taken from the BIND 9 code. It has been
24 * modified to remove the DNS-specific parts, and the BIND-specific
27 * The DNS-specific parts are now wrapped with the DNS_SUPPORT macro,
28 * and the BIND-specific parts are now wrapped with the BIND_SUPPORT
46 #include <isc/boolean.h>
47 #include <isc/commandline.h>
48 #include <isc/print.h>
49 #include <isc/string.h>
53 #include <dns/compress.h>
54 #include <omapip/result.h>
55 #endif /* DNS_SUPPORT */
58 #define isc_commandline_parse getopt
59 #define isc_commandline_argument optarg
60 #define isc_commandline_option optopt
61 #endif /* BIND_SUPPORT */
66 static const char *Usage
=
67 "\t-a : run all tests\n"
68 "\t-b <dir> : chdir to dir before running tests"
69 "\t-c <config_file> : use specified config file\n"
70 "\t-d <debug_level> : set debug level to debug_level\n"
71 "\t-h : print test info\n"
72 "\t-u : print usage info\n"
73 "\t-n <test_name> : run specified test name\n"
74 "\t-t <test_number> : run specified test number\n"
75 "\t-x : don't execute tests in a subproc\n"
76 "\t-q <timeout> : use 'timeout' as the timeout value\n";
78 * -a --> run all tests
79 * -b dir --> chdir to dir before running tests
80 * -c config --> use config file 'config'
81 * -d --> turn on api debugging
82 * -h --> print out available test names
83 * -u --> print usage info
84 * -n name --> run test named name
86 * -x --> don't execute testcases in a subproc
87 * -q timeout --> use 'timeout' as the timeout value
90 #define T_MAXTESTS 256 /*% must be 0 mod 8 */
92 #define T_DEFAULT_CONFIG "t_config"
101 static const char * T_config
;
102 static char T_tvec
[T_MAXTESTS
/ 8];
103 static char * T_env
[T_MAXENV
+ 1];
104 static char T_buf
[T_BIGBUF
];
108 t_initconf(const char *path
);
111 t_dumpconf(const char *path
);
114 t_putinfo(const char *key
, const char *info
);
117 t_getdate(char *buf
, size_t buflen
);
128 t_sighandler(int sig
) {
133 main(int argc
, char **argv
) {
145 isc_mem_debugging
= ISC_MEM_DEBUGRECORD
;
146 #endif /* BIND_SUPPORT */
149 T_timeout
= T_TCTOUT
;
152 * -a option is now default.
154 memset(T_tvec
, 0xffff, sizeof(T_tvec
));
159 while ((c
= isc_commandline_parse(argc
, argv
, ":at:c:d:n:huxq:b:"))
163 * Flag all tests to be run.
165 memset(T_tvec
, 0xffff, sizeof(T_tvec
));
168 T_dir
= isc_commandline_argument
;
171 tnum
= atoi(isc_commandline_argument
);
172 if ((tnum
> 0) && (tnum
< T_MAXTESTS
)) {
175 * Turn off effect of -a default
176 * and allow multiple -t and -n
179 memset(T_tvec
, 0, sizeof(T_tvec
));
183 * Flag test tnum to be run.
186 T_tvec
[tnum
/ 8] |= (0x01 << (tnum
% 8));
190 T_config
= isc_commandline_argument
;
193 T_debug
= atoi(isc_commandline_argument
);
196 pts
= &T_testlist
[0];
198 while (pts
->pfv
!= NULL
) {
199 if (! strcmp(pts
->func_name
,
200 isc_commandline_argument
)) {
206 T_tvec
[tnum
/8] |= (0x01 << (tnum
%8));
212 if (pts
->pfv
== NULL
) {
213 fprintf(stderr
, "no such test %s\n",
214 isc_commandline_argument
);
230 T_timeout
= atoi(isc_commandline_argument
);
233 fprintf(stderr
, "Option -%c requires an argument\n",
234 isc_commandline_option
);
238 fprintf(stderr
, "Unrecognized option -%c\n",
239 isc_commandline_option
);
249 IGNORE_RET (chdir(T_dir
));
252 * We don't want buffered output.
255 (void)setbuf(stdout
, NULL
);
256 (void)setbuf(stderr
, NULL
);
263 sigfillset(&sa
.sa_mask
);
267 * This is mostly here for NetBSD's pthread implementation, until
268 * people catch up to the latest unproven-pthread package.
270 sa
.sa_handler
= SIG_DFL
;
271 (void)sigaction(SIGCHLD
, &sa
, NULL
);
274 sa
.sa_handler
= t_sighandler
;
275 (void)sigaction(SIGINT
, &sa
, NULL
);
276 (void)sigaction(SIGALRM
, &sa
, NULL
);
279 * Output start stanza to journal.
282 snprintf(T_buf
, sizeof(T_buf
), "%s:", argv
[0]);
284 (void) t_getdate(T_buf
+ len
, T_BIGBUF
- len
);
285 t_putinfo("S", T_buf
);
288 * Setup the test environment using the config file.
291 if (T_config
== NULL
)
292 T_config
= T_DEFAULT_CONFIG
;
294 t_initconf(T_config
);
296 t_dumpconf(T_config
);
299 * Now invoke all the test cases.
303 pts
= &T_testlist
[0];
304 while (*pts
->pfv
!= NULL
) {
305 if (T_tvec
[tnum
/ 8] & (0x01 << (tnum
% 8))) {
311 } else if (T_pid
> 0) {
314 sa
.sa_handler
= t_sighandler
;
315 (void)sigaction(SIGALRM
, &sa
, NULL
);
318 deadpid
= (pid_t
) -1;
319 while (deadpid
!= T_pid
) {
321 waitpid(T_pid
, &status
, 0);
322 if (deadpid
== T_pid
) {
323 if (WIFSIGNALED(status
)) {
324 if (WTERMSIG(status
) ==
327 "the test case timed out\n");
330 "the test case caused exception %d\n",
332 t_result(T_UNRESOLVED
);
334 } else if ((deadpid
== -1) &&
337 kill(T_pid
, SIGTERM
);
340 else if ((deadpid
== -1) &&
341 ((errno
== ECHILD
) ||
347 sa
.sa_handler
= SIG_IGN
;
348 (void)sigaction(SIGALRM
, &sa
, NULL
);
350 t_info("fork failed, errno == %d\n",
352 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
, ...) {
375 (void)printf("T:%s:%d:%s\n", component
, anum
, class == T_REQUIRED
?
379 * Format text to a buffer.
381 va_start(args
, what
);
382 (void)vsnprintf(T_buf
, sizeof(T_buf
), what
, args
);
385 (void)t_putinfo("A", T_buf
);
390 t_info(const char *format
, ...) {
393 va_start(args
, format
);
394 (void) vsnprintf(T_buf
, sizeof(T_buf
), format
, args
);
396 (void) t_putinfo("I", T_buf
);
400 t_result(int result
) {
430 t_getenv(const char *name
) {
442 if (strncmp(*p
, name
, len
) == 0) {
443 if ( *(*p
+ len
) == '=') {
456 * Read in the config file at path, initializing T_env.
458 * note: no format checking for now ...
463 t_initconf(const char *path
) {
472 fp
= fopen(path
, "r");
476 while (n
< T_MAXENV
) {
480 if ((**p
== '#') || (strchr(*p
, '=') == NULL
)) {
482 * Skip comments and other junk.
498 * Dump T_env to stdout.
503 t_dumpconf(const char *path
) {
509 fp
= fopen(path
, "r");
513 printf("C:%s\n", *p
);
524 * Read a newline or EOF terminated string from fp.
526 * return a malloc'd buf containing the string with
527 * the newline converted to a '\0'.
531 * Caller is responsible for freeing buf.
545 old
= buf
= (char *) malloc(T_BUFSIZ
* sizeof(char));
549 while ((c
= fgetc(fp
)) != EOF
) {
558 buf
= (char *)realloc(buf
,
559 size
* sizeof(char));
567 if (c
== EOF
&& n
== 0U) {
576 fprintf(stderr
, "malloc/realloc failed %d", errno
);
583 * Put info to log, using key.
584 * For now, just dump it out.
585 * Later format into pretty lines.
590 t_putinfo(const char *key
, const char *info
) {
596 rval
= printf("%s:%s", key
, info
);
601 t_getdate(char *buf
, size_t buflen
) {
608 n
= strftime(buf
, buflen
- 1, "%A %d %B %H:%M:%S %Y\n", p
);
609 return(n
!= 0U ? buf
: NULL
);
613 * Some generally used utilities.
616 struct dns_errormap
{
620 { ISC_R_SUCCESS
, "ISC_R_SUCCESS" },
621 { ISC_R_EXISTS
, "ISC_R_EXISTS" },
622 { ISC_R_NOTFOUND
, "ISC_R_NOTFOUND" },
623 { ISC_R_NOSPACE
, "ISC_R_NOSPACE" },
624 { ISC_R_UNEXPECTED
, "ISC_R_UNEXPECTED" },
625 { ISC_R_UNEXPECTEDEND
, "ISC_R_UNEXPECTEDEND" },
626 { ISC_R_RANGE
, "ISC_R_RANGE" },
627 { DNS_R_LABELTOOLONG
, "DNS_R_LABELTOOLONG" },
628 { DNS_R_BADESCAPE
, "DNS_R_BADESCAPE" },
629 /* { DNS_R_BADBITSTRING, "DNS_R_BADBITSTRING" }, */
630 /* { DNS_R_BITSTRINGTOOLONG, "DNS_R_BITSTRINGTOOLONG"}, */
631 { DNS_R_EMPTYLABEL
, "DNS_R_EMPTYLABEL" },
632 { DNS_R_BADDOTTEDQUAD
, "DNS_R_BADDOTTEDQUAD" },
633 { DNS_R_UNKNOWN
, "DNS_R_UNKNOWN" },
634 { DNS_R_BADLABELTYPE
, "DNS_R_BADLABELTYPE" },
635 { DNS_R_BADPOINTER
, "DNS_R_BADPOINTER" },
636 { DNS_R_TOOMANYHOPS
, "DNS_R_TOOMANYHOPS" },
637 { DNS_R_DISALLOWED
, "DNS_R_DISALLOWED" },
638 { DNS_R_EXTRATOKEN
, "DNS_R_EXTRATOKEN" },
639 { DNS_R_EXTRADATA
, "DNS_R_EXTRADATA" },
640 { DNS_R_TEXTTOOLONG
, "DNS_R_TEXTTOOLONG" },
641 { DNS_R_SYNTAX
, "DNS_R_SYNTAX" },
642 { DNS_R_BADCKSUM
, "DNS_R_BADCKSUM" },
643 { DNS_R_BADAAAA
, "DNS_R_BADAAAA" },
644 { DNS_R_NOOWNER
, "DNS_R_NOOWNER" },
645 { DNS_R_NOTTL
, "DNS_R_NOTTL" },
646 { DNS_R_BADCLASS
, "DNS_R_BADCLASS" },
647 { DNS_R_PARTIALMATCH
, "DNS_R_PARTIALMATCH" },
648 { DNS_R_NEWORIGIN
, "DNS_R_NEWORIGIN" },
649 { DNS_R_UNCHANGED
, "DNS_R_UNCHANGED" },
650 { DNS_R_BADTTL
, "DNS_R_BADTTL" },
651 { DNS_R_NOREDATA
, "DNS_R_NOREDATA" },
652 { DNS_R_CONTINUE
, "DNS_R_CONTINUE" },
653 { DNS_R_DELEGATION
, "DNS_R_DELEGATION" },
654 { DNS_R_GLUE
, "DNS_R_GLUE" },
655 { DNS_R_DNAME
, "DNS_R_DNAME" },
656 { DNS_R_CNAME
, "DNS_R_CNAME" },
657 { DNS_R_NXDOMAIN
, "DNS_R_NXDOMAIN" },
658 { DNS_R_NXRRSET
, "DNS_R_NXRRSET" },
659 { DNS_R_BADDB
, "DNS_R_BADDB" },
660 { DNS_R_ZONECUT
, "DNS_R_ZONECUT" },
661 { DNS_R_NOTZONETOP
, "DNS_R_NOTZONETOP" },
662 { DNS_R_SEENINCLUDE
, "DNS_R_SEENINCLUDE" },
663 { DNS_R_SINGLETON
, "DNS_R_SINGLETON" },
664 { (isc_result_t
)0, NULL
}
668 t_dns_result_fromtext(char *name
) {
671 struct dns_errormap
*pmap
;
673 result
= ISC_R_UNEXPECTED
;
676 while (pmap
->text
!= NULL
) {
677 if (strcmp(name
, pmap
->text
) == 0)
682 if (pmap
->text
!= NULL
)
683 result
= pmap
->result
;
688 struct dc_method_map
{
689 unsigned int dc_method
;
691 } dc_method_map
[] = {
693 { DNS_COMPRESS_NONE
, "DNS_COMPRESS_NONE" },
694 { DNS_COMPRESS_GLOBAL14
, "DNS_COMPRESS_GLOBAL14" },
695 { DNS_COMPRESS_ALL
, "DNS_COMPRESS_ALL" },
700 t_dc_method_fromtext(char *name
) {
701 unsigned int dc_method
;
702 struct dc_method_map
*pmap
;
704 dc_method
= DNS_COMPRESS_NONE
;
706 pmap
= dc_method_map
;
707 while (pmap
->text
!= NULL
) {
708 if (strcmp(name
, pmap
->text
) == 0)
713 if (pmap
->text
!= NULL
)
714 dc_method
= pmap
->dc_method
;
718 #endif /* DNS_SUPPORT */
721 t_bustline(char *line
, char **toks
) {
727 while ((p
= strtok(line
, "\t")) && (cnt
< T_MAXTOKS
)) {
742 pts
= &T_testlist
[0];
744 printf("Available tests:\n");
745 while (pts
->func_name
) {
746 printf("\t%d\t%s\n", cnt
, pts
->func_name
);
754 printf("Usage:\n%s\n", Usage
);
758 t_eval(const char *filename
, int (*func
)(char **), int nargs
) {
767 char *tokens
[T_MAXTOKS
+ 1];
773 fp
= fopen(filename
, "r");
776 while ((p
= t_fgetbs(fp
)) != NULL
) {
781 * Skip comment lines.
783 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
788 cnt
= t_bustline(p
, tokens
);
790 result
= func(tokens
);
805 t_info("bad format in %s at line %d\n",
814 t_info("Missing datafile %s\n", filename
);
818 result
= T_UNRESOLVED
;
820 if (nfails
== 0 && nprobs
== 0 && npass
> 0)