diff options
Diffstat (limited to 'tools/regression/lib/libc')
87 files changed, 10358 insertions, 0 deletions
diff --git a/tools/regression/lib/libc/gen/Makefile b/tools/regression/lib/libc/gen/Makefile new file mode 100644 index 0000000..140b789 --- /dev/null +++ b/tools/regression/lib/libc/gen/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +TESTS= test-fpclassify test-wordexp + +.PHONY: tests +tests: ${TESTS} + for p in ${TESTS}; do ${.OBJDIR}/$$p; done + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/gen/test-fpclassify.c b/tools/regression/lib/libc/gen/test-fpclassify.c new file mode 100644 index 0000000..8431fe8 --- /dev/null +++ b/tools/regression/lib/libc/gen/test-fpclassify.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <assert.h> +#include <math.h> +#include <stdlib.h> + +int +main(void) +{ + + assert(fpclassify((float)0) == FP_ZERO); + assert(fpclassify((float)-0.0) == FP_ZERO); + assert(fpclassify((float)1) == FP_NORMAL); + assert(fpclassify((float)1000) == FP_NORMAL); +#ifndef __alpha__ + assert(fpclassify(0x1.2p-150f) == FP_SUBNORMAL); +#endif + assert(fpclassify(HUGE_VALF) == FP_INFINITE); + assert(fpclassify((float)HUGE_VAL) == FP_INFINITE); + assert(fpclassify((float)HUGE_VALL) == FP_INFINITE); + assert(fpclassify(NAN) == FP_NAN); + + assert(fpclassify((double)0) == FP_ZERO); + assert(fpclassify((double)-0) == FP_ZERO); + assert(fpclassify((double)1) == FP_NORMAL); + assert(fpclassify((double)1000) == FP_NORMAL); +#ifndef __alpha__ + assert(fpclassify(0x1.2p-1075) == FP_SUBNORMAL); +#endif + assert(fpclassify(HUGE_VAL) == FP_INFINITE); + assert(fpclassify((double)HUGE_VALF) == FP_INFINITE); + assert(fpclassify((double)HUGE_VALL) == FP_INFINITE); + assert(fpclassify((double)NAN) == FP_NAN); + + assert(fpclassify((long double)0) == FP_ZERO); + assert(fpclassify((long double)-0.0) == FP_ZERO); + assert(fpclassify((long double)1) == FP_NORMAL); + assert(fpclassify((long double)1000) == FP_NORMAL); +#ifndef __alpha__ + assert(fpclassify(0x1.2p-16383L) == FP_SUBNORMAL); +#endif + assert(fpclassify(HUGE_VALL) == FP_INFINITE); + assert(fpclassify((long double)HUGE_VALF) == FP_INFINITE); + assert(fpclassify((long double)HUGE_VAL) == FP_INFINITE); + assert(fpclassify((long double)NAN) == FP_NAN); + + printf("PASS fpclassify()\n"); + exit(0); +} diff --git a/tools/regression/lib/libc/gen/test-wordexp.c b/tools/regression/lib/libc/gen/test-wordexp.c new file mode 100644 index 0000000..49490d8 --- /dev/null +++ b/tools/regression/lib/libc/gen/test-wordexp.c @@ -0,0 +1,174 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wordexp() and wordfree() as specified by + * IEEE Std. 1003.1-2001. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wordexp.h> + +int +main(int argc, char *argv[]) +{ + wordexp_t we; + int r; + + /* Test that the macros are there. */ + (void)(WRDE_APPEND + WRDE_DOOFS + WRDE_NOCMD + WRDE_REUSE + + WRDE_SHOWERR + WRDE_UNDEF); + (void)(WRDE_BADCHAR + WRDE_BADVAL + WRDE_CMDSUB + WRDE_NOSPACE + + WRDE_SYNTAX); + + /* Simple test. */ + r = wordexp("hello world", &we, 0); + assert(r == 0); + assert(we.we_wordc == 2); + assert(strcmp(we.we_wordv[0], "hello") == 0); + assert(strcmp(we.we_wordv[1], "world") == 0); + assert(we.we_wordv[2] == NULL); + wordfree(&we); + + /* WRDE_DOOFS */ + we.we_offs = 3; + r = wordexp("hello world", &we, WRDE_DOOFS); + assert(r == 0); + assert(we.we_wordc == 2); + assert(we.we_wordv[0] == NULL); + assert(we.we_wordv[1] == NULL); + assert(we.we_wordv[2] == NULL); + assert(strcmp(we.we_wordv[3], "hello") == 0); + assert(strcmp(we.we_wordv[4], "world") == 0); + assert(we.we_wordv[5] == NULL); + wordfree(&we); + + /* WRDE_REUSE */ + r = wordexp("hello world", &we, 0); + r = wordexp("hello world", &we, WRDE_REUSE); + assert(r == 0); + assert(we.we_wordc == 2); + assert(strcmp(we.we_wordv[0], "hello") == 0); + assert(strcmp(we.we_wordv[1], "world") == 0); + assert(we.we_wordv[2] == NULL); + wordfree(&we); + + /* WRDE_APPEND */ + r = wordexp("this is", &we, 0); + assert(r == 0); + r = wordexp("a test", &we, WRDE_APPEND); + assert(r == 0); + assert(we.we_wordc == 4); + assert(strcmp(we.we_wordv[0], "this") == 0); + assert(strcmp(we.we_wordv[1], "is") == 0); + assert(strcmp(we.we_wordv[2], "a") == 0); + assert(strcmp(we.we_wordv[3], "test") == 0); + assert(we.we_wordv[4] == NULL); + wordfree(&we); + + /* WRDE_DOOFS + WRDE_APPEND */ + we.we_offs = 2; + r = wordexp("this is", &we, WRDE_DOOFS); + assert(r == 0); + r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFS); + assert(r == 0); + r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFS); + assert(r == 0); + assert(we.we_wordc == 6); + assert(we.we_wordv[0] == NULL); + assert(we.we_wordv[1] == NULL); + assert(strcmp(we.we_wordv[2], "this") == 0); + assert(strcmp(we.we_wordv[3], "is") == 0); + assert(strcmp(we.we_wordv[4], "a") == 0); + assert(strcmp(we.we_wordv[5], "test") == 0); + assert(strcmp(we.we_wordv[6], "of") == 0); + assert(strcmp(we.we_wordv[7], "wordexp") == 0); + assert(we.we_wordv[8] == NULL); + wordfree(&we); + + /* WRDE_UNDEF */ + r = wordexp("${dont_set_me}", &we, WRDE_UNDEF); + assert(r == WRDE_BADVAL); + + /* WRDE_NOCMD */ + r = wordexp("`date`", &we, WRDE_NOCMD); + assert(r == WRDE_CMDSUB); + r = wordexp("\"`date`\"", &we, WRDE_NOCMD); + assert(r == WRDE_CMDSUB); + r = wordexp("$(date)", &we, WRDE_NOCMD); + assert(r == WRDE_CMDSUB); + r = wordexp("\"$(date)\"", &we, WRDE_NOCMD); + assert(r == WRDE_CMDSUB); + r = wordexp("$((3+5))", &we, WRDE_NOCMD); + assert(r == 0); + r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE); + assert(r == 0); + r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE); + assert(r == 0); + r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE); + assert(r == 0); + wordfree(&we); + + /* WRDE_BADCHAR */ + r = wordexp("'\n|&;<>(){}'", &we, 0); + assert(r == 0); + r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE); + assert(r == 0); + r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE); + assert(r == 0); + wordfree(&we); + r = wordexp("test \n test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test | test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test & test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test ; test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test > test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test < test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test ( test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test ) test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test { test", &we, 0); + assert(r == WRDE_BADCHAR); + r = wordexp("test } test", &we, 0); + assert(r == WRDE_BADCHAR); + + printf("PASS wordexp()\n"); + printf("PASS wordfree()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/Makefile b/tools/regression/lib/libc/locale/Makefile new file mode 100644 index 0000000..5fb9a94 --- /dev/null +++ b/tools/regression/lib/libc/locale/Makefile @@ -0,0 +1,25 @@ +# $FreeBSD$ + +TESTS= test-mbrtowc \ + test-wcrtomb \ + test-mbsnrtowcs \ + test-mbsrtowcs \ + test-wcsnrtombs \ + test-wcsrtombs \ + test-btowc \ + test-mbrlen \ + test-mbtowc \ + test-wctomb \ + test-mbstowcs \ + test-wcstombs \ + test-mblen \ + test-iswctype \ + test-towctrans + +.PHONY: tests +tests: ${TESTS} + for p in ${TESTS}; do ${.OBJDIR}/$$p; done + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/locale/test-btowc.c b/tools/regression/lib/libc/locale/test-btowc.c new file mode 100644 index 0000000..9ed4582 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-btowc.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for btowc() and wctob() as specified by IEEE Std. 1003.1-2001 + * and ISO/IEC 9899:1999. + * + * The function is tested in the "C" and "ja_JP.eucJP" locales. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + int i; + + printf("1..2\n"); + + /* + * C/POSIX locale. + */ + assert(btowc(EOF) == WEOF); + assert(wctob(WEOF) == EOF); + for (i = 0; i < UCHAR_MAX; i++) + assert(btowc(i) == (wchar_t)i && i == (int)wctob(i)); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + assert(btowc('A') == L'A' && wctob(L'A') == 'A'); + assert(btowc(0xa3) == WEOF && wctob(0xa3c1) == EOF); + + printf("ok 1 - btowc()\n"); + printf("ok 2 - wctob()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-btowc.t b/tools/regression/lib/libc/locale/test-btowc.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-btowc.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-iswctype.c b/tools/regression/lib/libc/locale/test-iswctype.c new file mode 100644 index 0000000..ca9621a --- /dev/null +++ b/tools/regression/lib/libc/locale/test-iswctype.c @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wctype() and iswctype() as specified by + * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999. + * + * The functions are tested in the "C" and "ja_JP.eucJP" locales. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <locale.h> +#include <stdio.h> +#include <wchar.h> +#include <wctype.h> + +int +main(int argc, char *argv[]) +{ + wctype_t t; + int i, j; + struct { + const char *name; + int (*func)(wint_t); + } cls[] = { + { "alnum", iswalnum }, + { "alpha", iswalpha }, + { "blank", iswblank }, + { "cntrl", iswcntrl }, + { "digit", iswdigit }, + { "graph", iswgraph }, + { "lower", iswlower }, + { "print", iswprint }, + { "punct", iswpunct }, + { "space", iswspace }, + { "upper", iswupper }, + { "xdigit", iswxdigit } + }; + + printf("1..2\n"); + + /* + * C/POSIX locale. + */ + for (i = 0; i < sizeof(cls) / sizeof(*cls); i++) { + t = wctype(cls[i].name); + assert(t != 0); + for (j = 0; j < 256; j++) + assert(cls[i].func(j) == iswctype(j, t)); + } + t = wctype("elephant"); + assert(t == 0); + for (i = 0; i < 256; i++) + assert(iswctype(i, t) == 0); + + /* + * Japanese (EUC) locale. + */ + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + for (i = 0; i < sizeof(cls) / sizeof(*cls); i++) { + t = wctype(cls[i].name); + assert(t != 0); + for (j = 0; j < 65536; j++) + assert(cls[i].func(j) == iswctype(j, t)); + } + t = wctype("elephant"); + assert(t == 0); + for (i = 0; i < 65536; i++) + assert(iswctype(i, t) == 0); + + printf("ok 1 - iswctype()\n"); + printf("ok 2 - wctype()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-iswctype.t b/tools/regression/lib/libc/locale/test-iswctype.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-iswctype.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mblen.c b/tools/regression/lib/libc/locale/test-mblen.c new file mode 100644 index 0000000..dd07359 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mblen.c @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mblen(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1990. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main(int argc, char *argv[]) +{ + size_t len; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + assert(MB_CUR_MAX == 1); + + /* No shift states in C locale. */ + assert(mblen(NULL, 0) == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = '\0'; + assert(mblen(buf, 1) == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + assert(mblen(buf, 1) == 1); + + /* Incomplete character sequence. */ + buf[0] = '\0'; + assert(mblen(buf, 0) == -1); + assert(mblen(NULL, 0) == 0); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + /* No shift states in EUC. */ + assert(mblen(NULL, 0) == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = '\0'; + assert(mblen(buf, 1) == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + assert(mblen(buf, 1) == 1); + + /* Incomplete character sequence. */ + buf[0] = '\0'; + assert(mblen(buf, 0) == -1); + assert(mblen(NULL, 0) == 0); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + assert(mblen(buf, 1) == -1); + assert(mblen(NULL, 0) == 0); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + assert(mblen(buf, 2) == 2); + + printf("ok 1 - mblen()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mblen.t b/tools/regression/lib/libc/locale/test-mblen.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mblen.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mbrlen.c b/tools/regression/lib/libc/locale/test-mbrlen.c new file mode 100644 index 0000000..3198a77 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbrlen.c @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mbrlen(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + mbstate_t s; + size_t len; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + assert(MB_CUR_MAX == 1); + + /* Null wide character, internal state. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + assert(mbrlen(buf, 1, NULL) == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 1, &s) == 0); + + /* Latin letter A, internal state. */ + assert(mbrlen(NULL, 0, NULL) == 0); + buf[0] = 'A'; + assert(mbrlen(buf, 1, NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 1, &s) == 1); + + /* Incomplete character sequence. */ + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 0, &s) == (size_t)-2); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + /* Null wide character, internal state. */ + assert(mbrlen(NULL, 0, NULL) == 0); + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + assert(mbrlen(buf, 1, NULL) == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 1, &s) == 0); + + /* Latin letter A, internal state. */ + assert(mbrlen(NULL, 0, NULL) == 0); + buf[0] = 'A'; + assert(mbrlen(buf, 1, NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 1, &s) == 1); + + /* Incomplete character sequence (zero length). */ + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 0, &s) == (size_t)-2); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 1, &s) == (size_t)-2); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + memset(&s, 0, sizeof(s)); + assert(mbrlen(buf, 2, &s) == 2); + + printf("ok 1 - mbrlen()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mbrlen.t b/tools/regression/lib/libc/locale/test-mbrlen.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbrlen.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mbrtowc.c b/tools/regression/lib/libc/locale/test-mbrtowc.c new file mode 100644 index 0000000..e9a2ea0 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbrtowc.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mbrtowc(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + mbstate_t s; + size_t len; + wchar_t wc; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + assert(MB_CUR_MAX == 1); + + /* Null wide character, internal state. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + assert(mbrtowc(&wc, buf, 1, NULL) == 0); + assert(wc == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + assert(mbrtowc(&wc, buf, 1, &s) == 0); + assert(wc == 0); + + /* Latin letter A, internal state. */ + assert(mbrtowc(NULL, 0, 0, NULL) == 0); + buf[0] = 'A'; + assert(mbrtowc(&wc, buf, 1, NULL) == 1); + assert(wc == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + assert(mbrtowc(&wc, buf, 1, &s) == 1); + assert(wc == L'A'); + + /* Incomplete character sequence. */ + wc = L'z'; + memset(&s, 0, sizeof(s)); + assert(mbrtowc(&wc, buf, 0, &s) == (size_t)-2); + assert(wc == L'z'); + + /* Check that mbrtowc() doesn't access the buffer when n == 0. */ + wc = L'z'; + memset(&s, 0, sizeof(s)); + buf[0] = '\0'; + assert(mbrtowc(&wc, buf, 0, &s) == (size_t)-2); + assert(wc == L'z'); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + /* Null wide character, internal state. */ + assert(mbrtowc(NULL, 0, 0, NULL) == 0); + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + assert(mbrtowc(&wc, buf, 1, NULL) == 0); + assert(wc == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + assert(mbrtowc(&wc, buf, 1, &s) == 0); + assert(wc == 0); + + /* Latin letter A, internal state. */ + assert(mbrtowc(NULL, 0, 0, NULL) == 0); + buf[0] = 'A'; + assert(mbrtowc(&wc, buf, 1, NULL) == 1); + assert(wc == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + assert(mbrtowc(&wc, buf, 1, &s) == 1); + assert(wc == L'A'); + + /* Incomplete character sequence (zero length). */ + wc = L'z'; + memset(&s, 0, sizeof(s)); + assert(mbrtowc(&wc, buf, 0, &s) == (size_t)-2); + assert(wc == L'z'); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + memset(&s, 0, sizeof(s)); + wc = 0; + assert(mbrtowc(&wc, buf, 1, &s) == (size_t)-2); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + memset(&s, 0, sizeof(s)); + wc = 0; + assert(mbrtowc(&wc, buf, 2, &s) == 2); + assert(wc == 0xa3c1); + + /* Test restarting behaviour. */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + memset(&s, 0, sizeof(s)); + wc = 0; + assert(mbrtowc(&wc, buf, 1, &s) == (size_t)-2); + assert(wc == 0); + buf[0] = 0xc1; + assert(mbrtowc(&wc, buf, 1, &s) == 1); + assert(wc == 0xa3c1); + + printf("ok 1 - mbrtowc()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mbrtowc.t b/tools/regression/lib/libc/locale/test-mbrtowc.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbrtowc.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mbsnrtowcs.c b/tools/regression/lib/libc/locale/test-mbsnrtowcs.c new file mode 100644 index 0000000..585dd4e --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbsnrtowcs.c @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mbsnrtowcs(). + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + char srcbuf[128]; + wchar_t dstbuf[128]; + char *src; + mbstate_t s; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Simple null terminated string. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + assert(wcscmp(dstbuf, L"hello") == 0); + assert(dstbuf[6] == 0xcccc); + assert(src == NULL); + + /* Simple null terminated string, stopping early. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 4, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 4); + assert(wmemcmp(dstbuf, L"hell", 4) == 0); + assert(dstbuf[5] == 0xcccc); + assert(src == srcbuf + 4); + + /* Not enough space in destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, 4, &s) == 4); + assert(wmemcmp(dstbuf, L"hell", 4) == 0); + assert(dstbuf[5] == 0xcccc); + assert(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsnrtowcs(NULL, (const char **)&src, 6, 0, &s) == 5); + + /* Null terminated string, internal dest. buffer, stopping early */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsnrtowcs(NULL, (const char **)&src, 4, 0, &s) == 4); + + /* Null terminated string, internal state. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) / + sizeof(*dstbuf), NULL) == 5); + assert(wcscmp(dstbuf, L"hello") == 0); + assert(dstbuf[6] == 0xcccc); + assert(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + assert(mbsnrtowcs(NULL, (const char **)&src, 6, 0, NULL) == 5); + + /* Empty source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + srcbuf[0] = '\0'; + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, 1, &s) == 0); + assert(dstbuf[0] == 0); + assert(dstbuf[1] == 0xcccc); + assert(src == NULL); + + /* Zero length destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, 0, &s) == 0); + assert(dstbuf[0] == 0xcccc); + assert(src == srcbuf); + + /* Zero length source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 0, 1, &s) == 0); + assert(dstbuf[0] == 0xcccc); + assert(src == srcbuf); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 8, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + assert(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 && + dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0); + assert(src == NULL); + + /* Partial character. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 4); + assert(src == srcbuf + 6); + assert(!mbsinit(&s)); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 1); + assert(src == srcbuf + 7); + assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 0); + assert(src == NULL); + + printf("ok 1 - mbsnrtowcs()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mbsnrtowcs.t b/tools/regression/lib/libc/locale/test-mbsnrtowcs.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbsnrtowcs.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mbsrtowcs.c b/tools/regression/lib/libc/locale/test-mbsrtowcs.c new file mode 100644 index 0000000..dd6a7e1 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbsrtowcs.c @@ -0,0 +1,150 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mbsrtowcs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + char srcbuf[128]; + wchar_t dstbuf[128]; + char *src; + mbstate_t s; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Simple null terminated string. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + assert(wcscmp(dstbuf, L"hello") == 0); + assert(dstbuf[6] == 0xcccc); + assert(src == NULL); + + /* Not enough space in destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsrtowcs(dstbuf, (const char **)&src, 4, &s) == 4); + assert(wmemcmp(dstbuf, L"hell", 4) == 0); + assert(dstbuf[5] == 0xcccc); + assert(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(mbsrtowcs(NULL, (const char **)&src, 0, &s) == 5); + + /* Null terminated string, internal state. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + src = srcbuf; + assert(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) / + sizeof(*dstbuf), NULL) == 5); + assert(wcscmp(dstbuf, L"hello") == 0); + assert(dstbuf[6] == 0xcccc); + assert(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + assert(mbsrtowcs(NULL, (const char **)&src, 0, NULL) == 5); + + /* Empty source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + srcbuf[0] = '\0'; + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsrtowcs(dstbuf, (const char **)&src, 1, &s) == 0); + assert(dstbuf[0] == 0); + assert(dstbuf[1] == 0xcccc); + assert(src == NULL); + + /* Zero length destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsrtowcs(dstbuf, (const char **)&src, 0, &s) == 0); + assert(dstbuf[0] == 0xcccc); + assert(src == srcbuf); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) / + sizeof(*dstbuf), &s) == 5); + assert(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 && + dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0); + assert(src == NULL); + + printf("ok 1 - mbsrtowcs()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mbsrtowcs.t b/tools/regression/lib/libc/locale/test-mbsrtowcs.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbsrtowcs.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mbstowcs.c b/tools/regression/lib/libc/locale/test-mbstowcs.c new file mode 100644 index 0000000..18039dd --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbstowcs.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mbstowcs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + char srcbuf[128]; + wchar_t dstbuf[128]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Simple null terminated string. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5); + assert(wcscmp(dstbuf, L"hello") == 0); + assert(dstbuf[6] == 0xcccc); + + /* Not enough space in destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbstowcs(dstbuf, srcbuf, 4) == 4); + assert(wmemcmp(dstbuf, L"hell", 4) == 0); + assert(dstbuf[5] == 0xcccc); + + /* Null terminated string, internal dest. buffer (XSI extension) */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + assert(mbstowcs(NULL, srcbuf, 0) == 5); + + /* Empty source buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + srcbuf[0] = '\0'; + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbstowcs(dstbuf, srcbuf, 1) == 0); + assert(dstbuf[0] == 0); + assert(dstbuf[1] == 0xcccc); + + /* Zero length destination buffer. */ + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "hello"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbstowcs(dstbuf, srcbuf, 0) == 0); + assert(dstbuf[0] == 0xcccc); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + memset(srcbuf, 0xcc, sizeof(srcbuf)); + strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3"); + wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf)); + assert(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5); + assert(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 && + dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0); + + printf("ok 1 - mbstowcs()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mbstowcs.t b/tools/regression/lib/libc/locale/test-mbstowcs.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbstowcs.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-mbtowc.c b/tools/regression/lib/libc/locale/test-mbtowc.c new file mode 100644 index 0000000..5ee070c --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbtowc.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for mbtowc(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1990. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main(int argc, char *argv[]) +{ + size_t len; + wchar_t wc; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + assert(MB_CUR_MAX == 1); + + /* No shift states in C locale. */ + assert(mbtowc(NULL, NULL, 0) == 0); + + /* Null wide character. */ + wc = 0xcccc; + memset(buf, 0, sizeof(buf)); + assert(mbtowc(&wc, buf, 1) == 0); + assert(wc == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + assert(mbtowc(&wc, buf, 1) == 1); + assert(wc == L'A'); + + /* Incomplete character sequence. */ + wc = L'z'; + buf[0] = '\0'; + assert(mbtowc(&wc, buf, 0) == -1); + assert(wc == L'z'); + assert(mbtowc(NULL, NULL, 0) == 0); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + /* Null wide character */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0; + wc = 0xcccc; + assert(mbtowc(&wc, buf, 1) == 0); + assert(wc == 0); + + /* Latin letter A. */ + buf[0] = 'A'; + assert(mbtowc(&wc, buf, 1) == 1); + assert(wc == L'A'); + + /* Incomplete character sequence (zero length). */ + wc = L'z'; + buf[0] = '\0'; + assert(mbtowc(&wc, buf, 0) == -1); + assert(wc == L'z'); + assert(mbtowc(NULL, NULL, 0) == 0); + + /* Incomplete character sequence (truncated double-byte). */ + memset(buf, 0xcc, sizeof(buf)); + buf[0] = 0xa3; + buf[1] = 0x00; + wc = L'z'; + assert(mbtowc(&wc, buf, 1) == -1); + assert(wc == L'z'); + assert(mbtowc(NULL, NULL, 0) == 0); + + /* Same as above, but complete. */ + buf[1] = 0xc1; + assert(mbtowc(&wc, buf, 2) == 2); + assert(wc == 0xa3c1); + + printf("ok 1 - mbtowc()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-mbtowc.t b/tools/regression/lib/libc/locale/test-mbtowc.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbtowc.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-towctrans.c b/tools/regression/lib/libc/locale/test-towctrans.c new file mode 100644 index 0000000..6c0e428 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-towctrans.c @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wctrans() and towctrans() as specified by + * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999. + * + * The functions are tested in the "C" and "ja_JP.eucJP" locales. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <locale.h> +#include <stdio.h> +#include <wchar.h> +#include <wctype.h> + +int +main(int argc, char *argv[]) +{ + wctype_t t; + int i, j; + struct { + const char *name; + wint_t (*func)(wint_t); + } tran[] = { + { "tolower", towlower }, + { "toupper", towupper }, + }; + + printf("1..2\n"); + + /* + * C/POSIX locale. + */ + for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) { + t = wctrans(tran[i].name); + assert(t != 0); + for (j = 0; j < 256; j++) + assert(tran[i].func(j) == towctrans(j, t)); + } + t = wctrans("elephant"); + assert(t == 0); + for (i = 0; i < 256; i++) + assert(towctrans(i, t) == i); + + /* + * Japanese (EUC) locale. + */ + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) { + t = wctrans(tran[i].name); + assert(t != 0); + for (j = 0; j < 65536; j++) + assert(tran[i].func(j) == towctrans(j, t)); + } + t = wctrans("elephant"); + assert(t == 0); + for (i = 0; i < 65536; i++) + assert(towctrans(i, t) == i); + + printf("ok 1 - towctrans()\n"); + printf("ok 2 - wctrans()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-towctrans.t b/tools/regression/lib/libc/locale/test-towctrans.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-towctrans.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-wcrtomb.c b/tools/regression/lib/libc/locale/test-wcrtomb.c new file mode 100644 index 0000000..d7ec029 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcrtomb.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wcrtomb(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + mbstate_t s; + size_t len; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + assert(MB_CUR_MAX == 1); + + /* + * If the buffer argument is NULL, wc is implicitly L'\0', + * wcrtomb() resets its internal state. + */ + assert(wcrtomb(NULL, L'\0', NULL) == 1); + assert(wcrtomb(NULL, UCHAR_MAX + 1, NULL) == 1); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'\0', &s); + assert(len == 1); + assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A, internal state. */ + assert(wcrtomb(NULL, L'\0', NULL) == 1); + assert(wcrtomb(NULL, L'A', NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'A', &s); + assert(len == 1); + assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Invalid code. */ + assert(wcrtomb(buf, UCHAR_MAX + 1, NULL) == (size_t)-1); + assert(errno == EILSEQ); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX == 3); + + /* + * If the buffer argument is NULL, wc is implicitly L'\0', + * wcrtomb() resets its internal state. + */ + assert(wcrtomb(NULL, L'\0', NULL) == 1); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'\0', &s); + assert(len == 1); + assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A, internal state. */ + assert(wcrtomb(NULL, L'\0', NULL) == 1); + assert(wcrtomb(NULL, L'A', NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, L'A', &s); + assert(len == 1); + assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Full width letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + len = wcrtomb(buf, 0xa3c1, &s); + assert(len == 2); + assert((unsigned char)buf[0] == 0xa3 && + (unsigned char)buf[1] == 0xc1 && + (unsigned char)buf[2] == 0xcc); + + printf("ok 1 - wcrtomb()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-wcrtomb.t b/tools/regression/lib/libc/locale/test-wcrtomb.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcrtomb.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-wcsnrtombs.c b/tools/regression/lib/libc/locale/test-wcsnrtombs.c new file mode 100644 index 0000000..2290cac --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcsnrtombs.c @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wcsnrtombs(). + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + wchar_t srcbuf[128]; + char dstbuf[128]; + wchar_t *src; + mbstate_t s; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Simple null terminated string. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf), + &s) == 5); + assert(strcmp(dstbuf, "hello") == 0); + assert((unsigned char)dstbuf[6] == 0xcc); + assert(src == NULL); + + /* Simple null terminated string, stopping early. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 4, sizeof(dstbuf), + &s) == 4); + assert(memcmp(dstbuf, "hell", 4) == 0); + assert((unsigned char)dstbuf[5] == 0xcc); + assert(src == srcbuf + 4); + + /* Not enough space in destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 4, + &s) == 4); + assert(memcmp(dstbuf, "hell", 4) == 0); + assert((unsigned char)dstbuf[5] == 0xcc); + assert(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(NULL, (const wchar_t **)&src, 6, sizeof(dstbuf), + &s) == 5); + + /* Null terminated string, internal dest. buffer, stopping early. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(NULL, (const wchar_t **)&src, 4, sizeof(dstbuf), + &s) == 4); + + /* Null terminated string, internal state. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf), + NULL) == 5); + assert(strcmp(dstbuf, "hello") == 0); + assert((unsigned char)dstbuf[6] == 0xcc); + assert(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + assert(wcsnrtombs(NULL, (const wchar_t **)&src, 6, 0, NULL) == 5); + + /* Empty source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = L'\0'; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 1, sizeof(dstbuf), + &s) == 0); + assert(dstbuf[0] == L'\0'); + + /* Zero length destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 0, &s) == 0); + assert((unsigned char)dstbuf[0] == 0xcc); + + /* Zero length source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 0, sizeof(dstbuf), + &s) == 0); + assert((unsigned char)dstbuf[0] == 0xcc); + assert(src == srcbuf); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = 0xA3C1; + srcbuf[1] = 0x0020; + srcbuf[2] = 0x0042; + srcbuf[3] = 0x0020; + srcbuf[4] = 0xA3C3; + srcbuf[5] = 0x0000; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf), + &s) == 7); + assert(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0); + assert((unsigned char)dstbuf[8] == 0xcc); + assert(src == NULL); + + /* Stopping early. */ + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 6, + &s) == 5); + assert(memcmp(dstbuf, "\xA3\xC1 B ", 5) == 0); + assert((unsigned char)dstbuf[5] == 0xcc); + assert(src == srcbuf + 4); + + printf("ok 1 - wcsnrtombs()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-wcsnrtombs.t b/tools/regression/lib/libc/locale/test-wcsnrtombs.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcsnrtombs.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-wcsrtombs.c b/tools/regression/lib/libc/locale/test-wcsrtombs.c new file mode 100644 index 0000000..48fe366 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcsrtombs.c @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wcsrtombs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + wchar_t srcbuf[128]; + char dstbuf[128]; + wchar_t *src; + mbstate_t s; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Simple null terminated string. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 5); + assert(strcmp(dstbuf, "hello") == 0); + assert((unsigned char)dstbuf[6] == 0xcc); + assert(src == NULL); + + /* Not enough space in destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsrtombs(dstbuf, (const wchar_t **)&src, 4, + &s) == 4); + assert(memcmp(dstbuf, "hell", 4) == 0); + assert((unsigned char)dstbuf[5] == 0xcc); + assert(src == srcbuf + 4); + + /* Null terminated string, internal dest. buffer */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsrtombs(NULL, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 5); + + /* Null terminated string, internal state. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + NULL) == 5); + assert(strcmp(dstbuf, "hello") == 0); + assert((unsigned char)dstbuf[6] == 0xcc); + assert(src == NULL); + + /* Null terminated string, internal state, internal dest. buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + src = srcbuf; + assert(wcsrtombs(NULL, (const wchar_t **)&src, 0, NULL) == 5); + + /* Empty source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = L'\0'; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 0); + assert(dstbuf[0] == L'\0'); + + /* Zero length destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsrtombs(dstbuf, (const wchar_t **)&src, 0, &s) == 0); + assert((unsigned char)dstbuf[0] == 0xcc); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = 0xA3C1; + srcbuf[1] = 0x0020; + srcbuf[2] = 0x0042; + srcbuf[3] = 0x0020; + srcbuf[4] = 0xA3C3; + srcbuf[5] = 0x0000; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + src = srcbuf; + memset(&s, 0, sizeof(s)); + assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf), + &s) == 7); + assert(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0); + assert((unsigned char)dstbuf[8] == 0xcc); + assert(src == NULL); + + printf("ok 1 - wcsrtombs()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-wcsrtombs.t b/tools/regression/lib/libc/locale/test-wcsrtombs.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcsrtombs.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-wcstombs.c b/tools/regression/lib/libc/locale/test-wcstombs.c new file mode 100644 index 0000000..f4a5770 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcstombs.c @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wcstombs(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +int +main(int argc, char *argv[]) +{ + wchar_t srcbuf[128]; + char dstbuf[128]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Simple null terminated string. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5); + assert(strcmp(dstbuf, "hello") == 0); + assert((unsigned char)dstbuf[6] == 0xcc); + + /* Not enough space in destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + assert(wcstombs(dstbuf, srcbuf, 4) == 4); + assert(memcmp(dstbuf, "hell", 4) == 0); + assert((unsigned char)dstbuf[5] == 0xcc); + + /* Null terminated string, internal dest. buffer */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + assert(wcstombs(NULL, srcbuf, sizeof(dstbuf)) == 5); + + /* Null terminated string, internal state. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5); + assert(strcmp(dstbuf, "hello") == 0); + assert((unsigned char)dstbuf[6] == 0xcc); + + /* Null terminated string, internal state, internal dest. buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + assert(wcstombs(NULL, srcbuf, 0) == 5); + + /* Empty source buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = L'\0'; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 0); + assert(dstbuf[0] == L'\0'); + + /* Zero length destination buffer. */ + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + wcscpy(srcbuf, L"hello"); + memset(dstbuf, 0xcc, sizeof(dstbuf)); + assert(wcstombs(dstbuf, srcbuf, 0) == 0); + assert((unsigned char)dstbuf[0] == 0xcc); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX > 1); + + wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf)); + srcbuf[0] = 0xA3C1; + srcbuf[1] = 0x0020; + srcbuf[2] = 0x0042; + srcbuf[3] = 0x0020; + srcbuf[4] = 0xA3C3; + srcbuf[5] = 0x0000; + memset(dstbuf, 0xcc, sizeof(dstbuf)); + assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 7); + assert(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0); + assert((unsigned char)dstbuf[8] == 0xcc); + + printf("ok 1 - wcstombs()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-wcstombs.t b/tools/regression/lib/libc/locale/test-wcstombs.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wcstombs.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/locale/test-wctomb.c b/tools/regression/lib/libc/locale/test-wctomb.c new file mode 100644 index 0000000..d55b3db --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wctomb.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for wctomb(), as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + * + * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and + * "ja_JP.eucJP". Other encodings are not tested. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main(int argc, char *argv[]) +{ + size_t len; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + assert(MB_CUR_MAX == 1); + + /* No shift states in C locale. */ + assert(wctomb(NULL, L'\0') == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'\0'); + assert(len == 1); + assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'A'); + assert(len == 1); + assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Invalid code. */ + assert(wctomb(buf, UCHAR_MAX + 1) == -1); + assert(wctomb(NULL, 0) == 0); + + /* + * Japanese (EUC) locale. + */ + + assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0); + assert(MB_CUR_MAX == 3); + + /* No shift states in EUC encoding. */ + assert(wctomb(NULL, L'\0') == 0); + + /* Null wide character. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'\0'); + assert(len == 1); + assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, L'A'); + assert(len == 1); + assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Full width letter A. */ + memset(buf, 0xcc, sizeof(buf)); + len = wctomb(buf, 0xa3c1); + assert(len == 2); + assert((unsigned char)buf[0] == 0xa3 && + (unsigned char)buf[1] == 0xc1 && + (unsigned char)buf[2] == 0xcc); + + printf("ok 1 - wctomb()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-wctomb.t b/tools/regression/lib/libc/locale/test-wctomb.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/locale/test-wctomb.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/net/Makefile b/tools/regression/lib/libc/net/Makefile new file mode 100644 index 0000000..a61741b --- /dev/null +++ b/tools/regression/lib/libc/net/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTS= test-ether test-eui64_aton test-eui64_line test-eui64_ntoa +CFLAGS+= -g -Wall + +.PHONY: tests +tests: ${TESTS} + for p in ${TESTS}; do ${.OBJDIR}/$$p; done + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/net/test-ether.c b/tools/regression/lib/libc/net/test-ether.c new file mode 100644 index 0000000..7408101 --- /dev/null +++ b/tools/regression/lib/libc/net/test-ether.c @@ -0,0 +1,235 @@ +/*- + * Copyright (c) 2007 Robert N. M. Watson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> + +#include <net/ethernet.h> + +#include <stdio.h> +#include <string.h> + +static int testnum; + +#define OK() do { \ + printf("ok %d %s\n", testnum, __func__); \ + return; \ +} while (0) + +#define NOTOK(why) do { \ + printf("not ok %d %s # %s\n", testnum, __func__, why); \ + return; \ +} while (0) + +#define TODO() NOTOK("TODO") + +static const char *ether_line_string = + "01:23:45:67:89:ab ether_line_hostname"; +static const char *ether_line_hostname = "ether_line_hostname"; +static const struct ether_addr ether_line_addr = { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } +}; + +static void +test_ether_line(void) +{ + struct ether_addr e; + char hostname[256]; + + testnum++; + if (ether_line(ether_line_string, &e, hostname) != 0) + NOTOK("returned error"); + if (bcmp(&e, ðer_line_addr, ETHER_ADDR_LEN) != 0) + NOTOK("bad address"); + if (strcmp(hostname, ether_line_hostname) != 0) { + printf("hostname: %s\n", hostname); + NOTOK("bad hostname"); + } + OK(); +} + +static const char *ether_line_bad_1_string = "x"; + +static void +test_ether_line_bad_1(void) +{ + struct ether_addr e; + char hostname[256]; + + testnum++; + if (ether_line(ether_line_bad_1_string, &e, hostname) == 0) + NOTOK("returned success"); + OK(); +} + +static const char *ether_line_bad_2_string = "x x"; + +static void +test_ether_line_bad_2(void) +{ + struct ether_addr e; + char hostname[256]; + + testnum++; + if (ether_line(ether_line_bad_2_string, &e, hostname) == 0) + NOTOK("returned success"); + OK(); +} + +static const char *ether_aton_string = "01:23:45:67:89:ab"; +static const struct ether_addr ether_aton_addr = { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } +}; + +static void +test_ether_aton_r(void) +{ + struct ether_addr e, *ep; + + testnum++; + ep = ether_aton_r(ether_aton_string, &e); + if (ep == NULL) + NOTOK("returned NULL"); + if (ep != &e) + NOTOK("returned different pointer"); + if (bcmp(&e, ðer_aton_addr, ETHER_ADDR_LEN) != 0) + NOTOK("bad address"); + OK(); +} + +static const char *ether_aton_bad_string = "x"; + +static void +test_ether_aton_r_bad(void) +{ + struct ether_addr e, *ep; + + testnum++; + ep = ether_aton_r(ether_aton_bad_string, &e); + if (ep == &e) + NOTOK("returned success"); + if (ep != NULL) + NOTOK("returned different pointer"); + OK(); +} + +static void +test_ether_aton(void) +{ + struct ether_addr *ep; + + testnum++; + ep = ether_aton(ether_aton_string); + if (ep == NULL) + NOTOK("returned NULL"); + if (bcmp(ep, ðer_aton_addr, ETHER_ADDR_LEN) != 0) + NOTOK("bad address"); + OK(); +} + +static void +test_ether_aton_bad(void) +{ + struct ether_addr *ep; + + testnum++; + ep = ether_aton(ether_aton_bad_string); + if (ep != NULL) + NOTOK("returned success"); + OK(); +} + +static const char *ether_ntoa_string = "01:23:45:67:89:ab"; +static const struct ether_addr ether_ntoa_addr = { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } +}; + +static void +test_ether_ntoa_r(void) +{ + char buf[256], *cp; + + testnum++; + cp = ether_ntoa_r(ðer_ntoa_addr, buf); + if (cp == NULL) + NOTOK("returned NULL"); + if (cp != buf) + NOTOK("returned different pointer"); + if (strcmp(cp, ether_ntoa_string) != 0) + NOTOK("bad string"); + OK(); +} + +static void +test_ether_ntoa(void) +{ + char *cp; + + testnum++; + cp = ether_ntoa(ðer_ntoa_addr); + if (cp == NULL) + NOTOK("returned NULL"); + if (strcmp(cp, ether_ntoa_string) != 0) + NOTOK("bad string"); + OK(); +} + +static void +test_ether_ntohost(void) +{ + + testnum++; + TODO(); +} + +static void +test_ether_hostton(void) +{ + + testnum++; + TODO(); +} + +int +main(int argc, char *argv[]) +{ + + printf("1..11\n"); + + test_ether_line(); + test_ether_line_bad_1(); + test_ether_line_bad_2(); + test_ether_aton_r(); + test_ether_aton_r_bad(); + test_ether_aton(); + test_ether_aton_bad(); + test_ether_ntoa_r(); + test_ether_ntoa(); + test_ether_ntohost(); + test_ether_hostton(); + return (0); +} diff --git a/tools/regression/lib/libc/net/test-ether.t b/tools/regression/lib/libc/net/test-ether.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/net/test-ether.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/net/test-eui64.h b/tools/regression/lib/libc/net/test-eui64.h new file mode 100644 index 0000000..ea82a10 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64.h @@ -0,0 +1,55 @@ +/* + * Copyright 2004 The Aerospace Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions, and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _TEST_EUI64_H +#define _TEST_EUI64_H + +struct eui64 test_eui64_id = {{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}}; +struct eui64 test_eui64_eui48 = {{0x00,0x11,0x22,0xFF,0xFE,0x33,0x44,0x55}}; +struct eui64 test_eui64_mac48 = {{0x00,0x11,0x22,0xFF,0xFF,0x33,0x44,0x55}}; + +#define test_eui64_id_ascii "00-11-22-33-44-55-66-77" +#define test_eui64_id_colon_ascii "00:11:22:33:44:55:66:77" +#define test_eui64_hex_ascii "0x0011223344556677" +#define test_eui64_eui48_ascii "00-11-22-ff-fe-33-44-55" +#define test_eui64_mac48_ascii "00-11-22-ff-fe-33-44-55" +#define test_eui64_mac_ascii "00-11-22-33-44-55" +#define test_eui64_mac_colon_ascii "00:11:22:33:44:55" +#define test_eui64_id_host "id" +#define test_eui64_eui48_host "eui-48" +#define test_eui64_mac48_host "mac-48" + +#define test_eui64_line_id "00-11-22-33-44-55-66-77 id" +#define test_eui64_line_id_colon "00:11:22:33:44:55:66:77 id" +#define test_eui64_line_eui48 "00-11-22-FF-fe-33-44-55 eui-48" +#define test_eui64_line_mac48 "00-11-22-FF-ff-33-44-55 mac-48" +#define test_eui64_line_eui48_6byte "00-11-22-33-44-55 eui-48" +#define test_eui64_line_eui48_6byte_c "00:11:22:33:44:55 eui-48" + +#endif /* !_TEST_EUI64_H */ diff --git a/tools/regression/lib/libc/net/test-eui64_aton.c b/tools/regression/lib/libc/net/test-eui64_aton.c new file mode 100644 index 0000000..e10f985 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64_aton.c @@ -0,0 +1,73 @@ +/* + * Copyright 2004 The Aerospace Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions, and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/eui64.h> +#include <stdio.h> +#include <string.h> + +#include "test-eui64.h" + +static int +test_str( const char *str, const struct eui64 *eui) +{ + struct eui64 e; + char buf[EUI64_SIZ]; + static int test = 0; + + test++; + + if (eui64_aton(str, &e) != 0 && + memcmp(&e, &eui, sizeof(struct eui64)) != 0) { + printf("not ok %d - : eui64_aton(%s)\n", test, str); + eui64_ntoa(&e, buf, sizeof(buf)); + printf("# got: %s\n", buf); + return (0); + } else { + printf("ok %d - eui64_aton(%s)\n", test, str); + return (1); + } + +} + +int +main(int argc, char **argv) +{ + + printf("1..5\n"); + + test_str(test_eui64_id_ascii, &test_eui64_id); + test_str(test_eui64_id_colon_ascii, &test_eui64_id); + test_str(test_eui64_mac_ascii, &test_eui64_eui48); + test_str(test_eui64_mac_colon_ascii, &test_eui64_eui48); + test_str(test_eui64_hex_ascii, &test_eui64_id); + + return (0); +} diff --git a/tools/regression/lib/libc/net/test-eui64_aton.t b/tools/regression/lib/libc/net/test-eui64_aton.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64_aton.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/net/test-eui64_line.c b/tools/regression/lib/libc/net/test-eui64_line.c new file mode 100644 index 0000000..714b460 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64_line.c @@ -0,0 +1,81 @@ +/* + * Copyright 2004 The Aerospace Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions, and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/eui64.h> +#include <stdio.h> +#include <string.h> + +#include "test-eui64.h" + +static int +test_line(const char *line, const struct eui64 *eui, const char *host) +{ + struct eui64 e; + char buf[256]; + static int test = 0; + + test++; + + if (eui64_line(line, &e, buf, sizeof(buf)) != 0 || + memcmp(&e, eui, sizeof(struct eui64)) != 0 || + strcmp(buf, host) != 0) { + printf("not ok %d - eui64_line(\"%s\")\n", test, line); + printf("# host = %s\n", buf); + eui64_ntoa(&e, buf, sizeof(buf)); + printf("# e = %s\n", buf); + return (0); + } else { + printf("ok %d - eui64_line(\"%s\")\n", test, line); + return (1); + } +} + +int +main(int argc, char **argv) +{ + + printf("1..6\n"); + + test_line(test_eui64_line_id, &test_eui64_id, + test_eui64_id_host); + test_line(test_eui64_line_id_colon, &test_eui64_id, + test_eui64_id_host); + test_line(test_eui64_line_eui48, &test_eui64_eui48, + test_eui64_eui48_host); + test_line(test_eui64_line_mac48, &test_eui64_mac48, + test_eui64_mac48_host); + test_line(test_eui64_line_eui48_6byte, &test_eui64_eui48, + test_eui64_eui48_host); + test_line(test_eui64_line_eui48_6byte_c, &test_eui64_eui48, + test_eui64_eui48_host); + + return (0); +} diff --git a/tools/regression/lib/libc/net/test-eui64_line.t b/tools/regression/lib/libc/net/test-eui64_line.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64_line.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/net/test-eui64_ntoa.c b/tools/regression/lib/libc/net/test-eui64_ntoa.c new file mode 100644 index 0000000..f7582f0 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64_ntoa.c @@ -0,0 +1,54 @@ +/* + * Copyright 2004 The Aerospace Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions, and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of The Aerospace Corporation may not be used to endorse or + * promote products derived from this software. + * + * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/eui64.h> +#include <stdio.h> +#include <string.h> + +#include "test-eui64.h" + +int +main(int argc, char **argv) +{ + char a[EUI64_SIZ]; + + printf("1..1\n"); + + if (eui64_ntoa(&test_eui64_id, a, sizeof(a)) == 0 && + strcmp(a, test_eui64_id_ascii) == 0) { + printf("ok 1 - eui64_ntoa\n"); + return (0); + } + printf("# a = '%s'\n", a); + + printf("not ok 1 - eui64_ntoa\n"); + return (0); +} diff --git a/tools/regression/lib/libc/net/test-eui64_ntoa.t b/tools/regression/lib/libc/net/test-eui64_ntoa.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/net/test-eui64_ntoa.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/nss/Makefile b/tools/regression/lib/libc/nss/Makefile new file mode 100644 index 0000000..8c8a514 --- /dev/null +++ b/tools/regression/lib/libc/nss/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTS= test-getaddr test-getgr test-gethostby test-getpw test-getproto\ + test-getrpc test-getserv test-getusershell +CFLAGS+= -g -Wall + +.PHONY: tests +tests: ${TESTS} + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/nss/README b/tools/regression/lib/libc/nss/README new file mode 100644 index 0000000..ba0373d --- /dev/null +++ b/tools/regression/lib/libc/nss/README @@ -0,0 +1,203 @@ +$FreeBSD$ + +A brief how-to +-------------- + +Each nsswitch regression test does 2 kinds of actions: +1. It runs a series of queries and tests the correctness of results. + There are 2 basic criterias which are used for that: + - numbers must be in the correct range + - certain pointers should not be NULL + +2. It makes a snapshot of the results of all queries that were made. + The idea of snapshots is to test that nsswitch-related function + calls behave equally (i.e. return same results for the same queries) + between system upgrades. When the test is executed and the snapshot is + already created, the test will compare the result of each query with + the appropriate result from the snapshot and will signal if they + differ. + +In order for nsswitch tests to be as useful as possible you should use +them in the following way: + +Step 1 (before upgrading your system). +Build the tests with "make" command and execute them with "prove -v" +command. If there are errors during the execution, then appropriate +nsswitch functions should be checked. Note, that errors on this state +can happen only if the particular function return incorrect data. + +After the stage 1 a number of "snapshot_[test name]" files will appear +in your test folder. + +Step 2 (after upgrading you system). +Rebuild the tests with "make clean; make" command and execute them +again with "prove -v" (check that "snapshot_[test name]" files +are in the same folder with tests). On this stage regression tests +will catch not only the correctness errors, but will also determine +the changes in nsswitch functions behaviour. + +In case of the test failure you will get the following message: + +To get more details about the error you should do the following: +Step 1. Run the test alone with debug output enabled. +Step 2. Mail the snapshot file and the debug test output to the +freebsd-current@ mailing list. + +Example testing session for getpwXXX() family of functions +---------------------------------------------------------- +1. make + +2. prove -v ./test-getpw.t + + test-getpw....1..8 + ok 1 - getpwnam() + ok 2 - getpwuid() + ok 3 - getpwent() + ok 4 - getpwent() 2-pass + ok 5 - building snapshot, if needed + ok 6 - getpwnam() snapshot + ok 7 - getpwuid() snapshot + ok 8 - getpwent() snapshot + ok + All tests successful. + Files=1, Tests=8, 1 wallclock secs ( 0.00 cusr + 0.20 csys = 0.20 CPU) + + +3. Upgrading the system. + +4. make clean; make + +5. prove -v ./test-getpw.t (suppose that something has gone wrong) + + test-getpw....1..8 + ok 1 - getpwnam() + ok 2 - getpwuid() + ok 3 - getpwent() + ok 4 - getpwent() 2-pass + ok 5 - building snapshot, if needed + not ok 6 - getpwnam() snapshot + ok 7 - getpwuid() snapshot + not ok 8 - getpwent() snapshot + FAILED tests 6, 8 + Failed 2/8 tests, 75.00% okay + Failed 1/1 test scripts, 0.00% okay. 2/8 subtests failed, 75.00% okay. + +6. We see that test number 6 failed. According to get-getpw.t, this test + is executed like this: + do_test 6 'getpwnam() snapshot' '-n -s snapshot_pwd' + + To determine why the test has failed, we need to run it in debug mode - + it means adding "-d" to the options list. + +7. ./test-getpw -dn -s snapshot_pwd + ... + testing getpwnam() with the following data: + toor:*:0:0:0::ne-again Superuser:/root::0:4831 + testing correctness with the following data: + toor:*:0:0:0::Bourne-again Superuser:/root::0:4831 + correct + not ok + +8. Here we can see that the data from snapshot (first "toor" line) and + the data received from the getpwnam() call (second "toor" line) are + different. It is the reason why the test has failed. If you can't + (or don't want) to investigate the problem by yourself, mail + the test debug output and the snapshot file to the developers list. + +Notes on using standalone nsswitch tests +---------------------------------------- + +All nsswitch tests have [-d] optional command line argument which enables +debug output. The debug output can be extremely helpful to determine the +cause of test failure. + +In all nsswitch tests -s <file> command line argument specifies the +snapshot file. If this file doesn't exist, it would be built during +test execution. If it already exists then it will be used to check +the results of particular function calls. This argument is mostly +optional, but some tests (test-getaddr and test-getusershell) force +it to be specified. + +test-gethostby and test-getaddr require the list of hostnames, that should +be queried during the test. This list must be specified via -f <file> +command line argument. Each hostname should occupy exactly one line +in the file. + +Detailed tests description +-------------------------- + +./test-getaddr - tests the getaddrinfo() function. + Usage: test-getaddr [-d] [-46] [-s <file>] -f <file> + -d - enable debug output + -4 - force IPv4 usage + -6 - force IPv6 usage + -s - build/use specified snapshot file + -f - use specified hostnames list for testing + +./test-getgr + Usage: test-getgr -nge2 [-d] [-s <file>] + -d - enable debug output + -n - test getgrnam(3) + -g - test getgrgid(3) + -e - test getgrent(3) + -2 - test getgrent(3) in 2-pass mode + -s - build/use specified snapshot file + +./test-gethostby + Usage: test-gethostby -na2i [-o] [-d] [-m46] [-s <file>] -f <file> + -n - test gethostbyname2(3) + -a - test gethostbyaddr(3) + -2 - test gethostbyname2(3) results to be equal with getaddrinfo(3) + results for the similar query + -i - test gethostbyaddr(3) results to be equal with getnameinfo(3) + results for the similar query + -o - use getipnodebyname(3)/getipnodebyaddr(3) for testing instead of + gethostbyname2(3)/gethostbyaddr(3) + -d - enable debug output + -m - force IPv4-to-IPv6 mapping + -4 - force IPv4 usage + -6 - force IPv6 usage + -s - build/use specified snapshot file + -f - use specified hostnames list for testing + +./test-getproto + Usage: test-getproto -nve2 [-d] [-s <file>] + -d - enable debug output + -n - test getprotobyname(3) + -v - test getprotobynumber(3) + -e - test getprotoent(3) + -2 - test getprotoent(3) in 2-pass mode + -s - build/use specified snapshot file + +./test-getpw + Usage: test-getpw -nue2 [-d] [-s <file>] + -d - enable debug output + -n - test getpwnam(3) + -u - test getpwuid(3) + -e - test getpwent(3) + -2 - test getpwent(3) in 2-pass mode + -s - build/use snapshot file + +./test-getrpc + Usage: test-getrpc -nve2 [-d] [-s <file>] + -d - enable debug output + -n - test getrpcbyname(3) + -v - test getrpcbynumber(3) + -e - test getrpcent(3) + -2 - test getrpcent(3) in 2-pass mode + -s - build/use specified snapshot file + +./test-getserv + Usage: test-getserv -npe2 [-d] [-s <file>] + -d - enable debug output + -n - test getservbyname(3) + -p - test getservbyport(3) + -e - test getservent(3) + -2 - test getservent(3) in 2-pass mode + -s - build/use specified snapshot file + +./test-getusershell + Usage: test-getusershell [-d] -s <file> + -d - enable debug output + -s - build/use specified snapshot file + diff --git a/tools/regression/lib/libc/nss/mach b/tools/regression/lib/libc/nss/mach new file mode 100644 index 0000000..d25d8d6 --- /dev/null +++ b/tools/regression/lib/libc/nss/mach @@ -0,0 +1,94 @@ +# $FreeBSD$ +localhost +above.warped.net +anoncvs.cirr.com +anoncvs.isc.netbsd.org +anoncvs.leo.org +anoncvs.netbsd.lt +anoncvs.netbsd.ro +anoncvs.netbsd.se +antioche.antioche.eu.org +boulder.tele.dk +centaurus.4web.cz +chur.math.ntnu.no +cnftp.bjpu.edu.cn +console.netbsd.org +cvs.fi.netbsd.org +cvs.mikrolahti.fi +cvs.netbsd.org +cvsup-netbsd.leo.org +cvsup.netbsd.se +cvsup.pasta.cs.uit.no +ftp.bitcon.no +ftp.chg.ru +ftp.duth.gr +ftp.estpak.ee +ftp.fsn.hu +ftp.funet.fi +ftp.grondar.za +ftp.leo.org +ftp.netbsd.lt +ftp.netbsd.org +ftp.nluug.nl +ftp.plig.org +ftp.uni-erlangen.de +ftp.xgate.co.kr +gd.tuwien.ac.at +gort.ludd.luth.se +grappa.unix-ag.uni-kl.de +info.wins.uva.nl +irc.warped.net +knug.youn.co.kr +lala.iri.co.jp +mail.jp.netbsd.org +mail.kr.netbsd.org +mail.netbsd.org +melanoma.cs.rmit.edu.au +mirror.aarnet.edu.au +mirror.netbsd.com.br +mirror03.inet.tele.dk +moon.vub.ac.be +nbwww.sergei.cc +net.bsd.cz +netbsd.3miasto.net +netbsd.4ka.mipt.ru +netbsd.apk.od.ua +netbsd.csie.nctu.edu.tw +netbsd.enderunix.org +netbsd.ftp.fu-berlin.de +netbsd.netlead.com.au +netbsd.nsysu.edu.tw +netbsd.pair.com +netbsd.stevens-tech.edu +netbsd.triada.bg +netbsd.unix.net.nz +netbsd.unixtech.be +netbsd.vejas.lt +netbsd.wagener-consulting.lu +netbsd.zarco.org +netbsdiso.interoute.net.uk +netbsdwww.bitcon.no +netbsdwww.cordef.com.pl +netbsdwww.cs.rmit.edu.au +netbsdwww.interoute.net.uk +news.gw.com +ns.netbsd.org +pigu.iri.co.jp +pluto.cdpa.nsysu.edu.tw +projects.slowass.net +server6.pasta.cs.uit.no +skeleton.phys.spbu.ru +snoopy.allbsd.org +spike.allbsd.org +sundry.netbsd.org +tanya.sergei.cc +web-a.fi.gw.com +web-a.us.gw.com +web.netbsd.mirror.arhea.net +www.en.netbsd.de +www.netbsd.cl +www.netbsd.nl +www.netbsd.org +www.netbsd.ro +zathras.netbsd.org +zeppo.rediris.es diff --git a/tools/regression/lib/libc/nss/test-getaddr.c b/tools/regression/lib/libc/nss/test-getaddr.c new file mode 100644 index 0000000..046d9db --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getaddr.c @@ -0,0 +1,538 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights rehted. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <assert.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stringlist.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETADDRINFO, + TEST_BUILD_SNAPSHOT +}; + +static int debug = 0; +static struct addrinfo hints; +static enum test_methods method = TEST_GETADDRINFO; + +DECLARE_TEST_DATA(addrinfo) +DECLARE_TEST_FILE_SNAPSHOT(addrinfo) +DECLARE_2PASS_TEST(addrinfo) + +static void clone_addrinfo(struct addrinfo *, struct addrinfo const *); +static int compare_addrinfo(struct addrinfo *, struct addrinfo *, void *); +static void dump_addrinfo(struct addrinfo *); +static void free_addrinfo(struct addrinfo *); + +static void sdump_addrinfo(struct addrinfo *, char *, size_t); + +IMPLEMENT_TEST_DATA(addrinfo) +IMPLEMENT_TEST_FILE_SNAPSHOT(addrinfo) +IMPLEMENT_2PASS_TEST(addrinfo) + +static void +clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + memcpy(dest, src, sizeof(struct addrinfo)); + if (src->ai_canonname != NULL) + dest->ai_canonname = strdup(src->ai_canonname); + + if (src->ai_addr != NULL) { + dest->ai_addr = (struct sockaddr *)malloc(src->ai_addrlen); + assert(dest->ai_addr != NULL); + memcpy(dest->ai_addr, src->ai_addr, src->ai_addrlen); + } + + if (src->ai_next != NULL) { + dest->ai_next = (struct addrinfo *)malloc( + sizeof(struct addrinfo)); + assert(dest->ai_next != NULL); + clone_addrinfo(dest->ai_next, src->ai_next); + } +} + +static int +compare_addrinfo_(struct addrinfo *ai1, struct addrinfo *ai2) +{ + if ((ai1 == NULL) || (ai2 == NULL)) + return (-1); + + if ((ai1->ai_flags != ai2->ai_flags) || + (ai1->ai_family != ai2->ai_family) || + (ai1->ai_socktype != ai2->ai_socktype) || + (ai1->ai_protocol != ai2->ai_protocol) || + (ai1->ai_addrlen != ai2->ai_addrlen) || + (((ai1->ai_addr == NULL) || (ai2->ai_addr == NULL)) && + (ai1->ai_addr != ai2->ai_addr)) || + (((ai1->ai_canonname == NULL) || (ai2->ai_canonname == NULL)) && + (ai1->ai_canonname != ai2->ai_canonname))) + return (-1); + + if ((ai1->ai_canonname != NULL) && + (strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0)) + return (-1); + + if ((ai1->ai_addr != NULL) && + (memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0)) + return (-1); + + if ((ai1->ai_next == NULL) && (ai2->ai_next == NULL)) + return (0); + else + return (compare_addrinfo_(ai1->ai_next, ai2->ai_next)); +} + +static int +compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2, void *mdata) +{ + int rv; + + if (debug) { + printf("testing equality of 2 addrinfo structures\n"); + } + + rv = compare_addrinfo_(ai1, ai2); + + if (debug) { + if (rv == 0) + printf("equal\n"); + else { + dump_addrinfo(ai1); + dump_addrinfo(ai2); + printf("not equal\n"); + } + } + + return (rv); +} + +void +free_addrinfo(struct addrinfo *ai) +{ + if (ai == NULL) + return; + + free(ai->ai_addr); + free(ai->ai_canonname); + free_addrinfo(ai->ai_next); +} + +void +sdump_addrinfo(struct addrinfo *ai, char *buffer, size_t buflen) +{ + int written, i; + + written = snprintf(buffer, buflen, "%d %d %d %d %d ", + ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, + ai->ai_addrlen); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + written = snprintf(buffer, buflen, "%s ", + ai->ai_canonname == NULL ? "(null)" : ai->ai_canonname); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (ai->ai_addr == NULL) { + written = snprintf(buffer, buflen, "(null)"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } else { + for (i = 0; i < ai->ai_addrlen; ++i ) { + written = snprintf(buffer, buflen, + i + 1 != ai->ai_addrlen ? "%d." : "%d", + ((unsigned char *)ai->ai_addr)[i]); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } + + if (ai->ai_next != NULL) { + written = snprintf(buffer, buflen, ":"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + sdump_addrinfo(ai->ai_next, buffer, buflen); + } +} + +void +dump_addrinfo(struct addrinfo *result) +{ + if (result != NULL) { + char buffer[2048]; + sdump_addrinfo(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +addrinfo_read_snapshot_addr(char *addr, unsigned char *result, size_t len) +{ + char *s, *ps, *ts; + + ps = addr; + while ( (s = strsep(&ps, ".")) != NULL) { + if (len == 0) + return (-1); + + *result = (unsigned char)strtol(s, &ts, 10); + ++result; + if (*ts != '\0') + return (-1); + + --len; + } + if (len != 0) + return (-1); + else + return (0); +} + +static int +addrinfo_read_snapshot_ai(struct addrinfo *ai, char *line) +{ + char *s, *ps, *ts; + int i, rv, *pi; + + rv = 0; + i = 0; + ps = line; + memset(ai, 0, sizeof(struct addrinfo)); + while ( (s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + case 1: + case 2: + case 3: + pi = &ai->ai_flags + i; + *pi = (int)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + case 4: + ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + case 5: + if (strcmp(s, "(null)") != 0) { + ai->ai_canonname = strdup(s); + assert(ai->ai_canonname != NULL); + } + break; + case 6: + if (strcmp(s, "(null)") != 0) { + ai->ai_addr = (struct sockaddr *)malloc( + ai->ai_addrlen); + assert(ai->ai_addr != NULL); + memset(ai->ai_addr, 0, ai->ai_addrlen); + rv = addrinfo_read_snapshot_addr(s, + (unsigned char *)ai->ai_addr, + ai->ai_addrlen); + + if (rv != 0) + goto fin; + } + break; + default: + /* NOTE: should not be reachable */ + rv = -1; + goto fin; + }; + + ++i; + } + +fin: + if ((i != 7) || (rv != 0)) { + free_addrinfo(ai); + memset(ai, 0, sizeof(struct addrinfo)); + return (-1); + } + + return (0); +} + +static int +addrinfo_read_snapshot_func(struct addrinfo *ai, char *line) +{ + struct addrinfo *ai2; + char *s, *ps; + int i, rv; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + rv = 0; + i = 0; + ps = line; + + s = strsep(&ps, ":"); + if (s == NULL) + return (-1); + + rv = addrinfo_read_snapshot_ai(ai, s); + if (rv != 0) + return (-1); + + ai2 = ai; + while ( (s = strsep(&ps, ":")) != NULL) { + ai2->ai_next = (struct addrinfo *)malloc( + sizeof(struct addrinfo)); + assert(ai2->ai_next != NULL); + memset(ai2->ai_next, 0, sizeof(struct addrinfo)); + + rv = addrinfo_read_snapshot_ai(ai2->ai_next, s); + if (rv != 0) { + free_addrinfo(ai); + return (-1); + } + + ai2 = ai2->ai_next; + } + + return (0); +} + +static int +addrinfo_test_correctness(struct addrinfo *ai, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_addrinfo(ai); + } + + if (ai == NULL) + goto errfin; + + if (!((ai->ai_family >= 0) && (ai->ai_family < AF_MAX))) + goto errfin; + + if ((ai->ai_socktype != 0) && (ai->ai_socktype != SOCK_STREAM) && + (ai->ai_socktype != SOCK_DGRAM) && (ai->ai_socktype != SOCK_RAW)) + goto errfin; + + if ((ai->ai_protocol != 0) && (ai->ai_protocol != IPPROTO_UDP) && + (ai->ai_protocol != IPPROTO_TCP)) + goto errfin; + + if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0) + goto errfin; + + if ((ai->ai_addrlen != ai->ai_addr->sa_len) || + (ai->ai_family != ai->ai_addr->sa_family)) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +static int +addrinfo_read_hostlist_func(struct addrinfo *ai, char *line) +{ + struct addrinfo *result; + int rv; + + if (debug) + printf("resolving %s: ", line); + rv = getaddrinfo(line, NULL, &hints, &result); + if (rv == 0) { + if (debug) + printf("found\n"); + + rv = addrinfo_test_correctness(result, NULL); + if (rv != 0) { + freeaddrinfo(result); + return (rv); + } + + clone_addrinfo(ai, result); + freeaddrinfo(result); + } else { + if (debug) + printf("not found\n"); + + memset(ai, 0, sizeof(struct addrinfo)); + } + return (0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s [-d] [-46] [-s <file]> -f <file>\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct addrinfo_test_data td, td_snap; + char *snapshot_file, *hostlist_file; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + hostlist_file = NULL; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + while ((c = getopt(argc, argv, "46dns:f:")) != -1) + switch (c) { + case '4': + hints.ai_family = PF_INET; + case '6': + hints.ai_family = PF_INET6; + break; + case 'd': + debug = 1; + break; + case 's': + snapshot_file = strdup(optarg); + method = TEST_BUILD_SNAPSHOT; + break; + case 'f': + hostlist_file = strdup(optarg); + break; + default: + usage(); + } + + TEST_DATA_INIT(addrinfo, &td, clone_addrinfo, free_addrinfo); + TEST_DATA_INIT(addrinfo, &td_snap, clone_addrinfo, free_addrinfo); + + if (hostlist_file == NULL) + usage(); + + if (access(hostlist_file, R_OK) != 0) { + if (debug) + printf("can't access the hostlist file %s\n", + hostlist_file); + + usage(); + } + + if (debug) + printf("building host lists from %s\n", hostlist_file); + + rv = TEST_SNAPSHOT_FILE_READ(addrinfo, hostlist_file, &td, + addrinfo_read_hostlist_func); + if (rv != 0) + goto fin; + + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the snapshot file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + rv = TEST_SNAPSHOT_FILE_READ(addrinfo, snapshot_file, + &td_snap, addrinfo_read_snapshot_func); + if (rv != 0) { + if (debug) + printf("error reading snapshot file\n"); + goto fin; + } + } + } + + switch (method) { + case TEST_GETADDRINFO: + if (snapshot_file != NULL) + rv = DO_2PASS_TEST(addrinfo, &td, &td_snap, + compare_addrinfo, NULL); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) { + rv = TEST_SNAPSHOT_FILE_WRITE(addrinfo, snapshot_file, &td, + sdump_addrinfo); + } + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(addrinfo, &td_snap); + TEST_DATA_DESTROY(addrinfo, &td); + free(hostlist_file); + free(snapshot_file); + return (rv); + +} + diff --git a/tools/regression/lib/libc/nss/test-getaddr.t b/tools/regression/lib/libc/nss/test-getaddr.t new file mode 100644 index 0000000..b3020f0 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getaddr.t @@ -0,0 +1,33 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..6 +#Tests with hints.ai_family is set to PF_UNSPEC +do_test 1 'getaddrinfo() (PF_UNSPEC)' '-f mach' +do_test 2 'getaddrinfo() snapshot (PF_UNSPEC)' '-f mach -s snapshot_ai' + +#Tests with hints.ai_family is set to PF_INET +do_test 3 'getaddrinfo() (PF_INET)' '-f mach' +do_test 4 'getaddrinfo() snapshot (PF_INET)' '-4 -f mach -s snapshot_ai4' + +#Tests with hints.ai_family is set to PF_INET6 +do_test 5 'getaddrinfo() (PF_INET6)' '-f mach' +do_test 6 'getaddrinfo() snapshot (PF_INET6)' '-6 -f mach -s snapshot_ai6' + diff --git a/tools/regression/lib/libc/nss/test-getgr.c b/tools/regression/lib/libc/nss/test-getgr.c new file mode 100644 index 0000000..1b573e8 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getgr.c @@ -0,0 +1,534 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights regrped. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stringlist.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETGRENT, + TEST_GETGRNAM, + TEST_GETGRGID, + TEST_GETGRENT_2PASS, + TEST_BUILD_SNAPSHOT +}; + +static int debug = 0; +static enum test_methods method = TEST_BUILD_SNAPSHOT; + +DECLARE_TEST_DATA(group) +DECLARE_TEST_FILE_SNAPSHOT(group) +DECLARE_1PASS_TEST(group) +DECLARE_2PASS_TEST(group) + +static void clone_group(struct group *, struct group const *); +static int compare_group(struct group *, struct group *, void *); +static void dump_group(struct group *); +static void free_group(struct group *); + +static void sdump_group(struct group *, char *, size_t); +static int group_read_snapshot_func(struct group *, char *); + +static int group_check_ambiguity(struct group_test_data *, + struct group *); +static int group_fill_test_data(struct group_test_data *); +static int group_test_correctness(struct group *, void *); +static int group_test_getgrnam(struct group *, void *); +static int group_test_getgrgid(struct group *, void *); +static int group_test_getgrent(struct group *, void *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(group) +IMPLEMENT_TEST_FILE_SNAPSHOT(group) +IMPLEMENT_1PASS_TEST(group) +IMPLEMENT_2PASS_TEST(group) + +static void +clone_group(struct group *dest, struct group const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + char **cp; + int members_num; + + memset(dest, 0, sizeof(struct group)); + + if (src->gr_name != NULL) { + dest->gr_name = strdup(src->gr_name); + assert(dest->gr_name != NULL); + } + + if (src->gr_passwd != NULL) { + dest->gr_passwd = strdup(src->gr_passwd); + assert(dest->gr_passwd != NULL); + } + dest->gr_gid = src->gr_gid; + + if (src->gr_mem != NULL) { + members_num = 0; + for (cp = src->gr_mem; *cp; ++cp) + ++members_num; + + dest->gr_mem = (char **)malloc( + (members_num + 1) * (sizeof(char *))); + assert(dest->gr_mem != NULL); + memset(dest->gr_mem, 0, (members_num+1) * (sizeof(char *))); + + for (cp = src->gr_mem; *cp; ++cp) { + dest->gr_mem[cp - src->gr_mem] = strdup(*cp); + assert(dest->gr_mem[cp - src->gr_mem] != NULL); + } + } +} + +static void +free_group(struct group *grp) +{ + char **cp; + + assert(grp != NULL); + + free(grp->gr_name); + free(grp->gr_passwd); + + for (cp = grp->gr_mem; *cp; ++cp) + free(*cp); + free(grp->gr_mem); +} + +static int +compare_group(struct group *grp1, struct group *grp2, void *mdata) +{ + char **c1, **c2; + + if (grp1 == grp2) + return (0); + + if ((grp1 == NULL) || (grp2 == NULL)) + goto errfin; + + if ((strcmp(grp1->gr_name, grp2->gr_name) != 0) || + (strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0) || + (grp1->gr_gid != grp2->gr_gid)) + goto errfin; + + c1 = grp1->gr_mem; + c2 = grp2->gr_mem; + + if ((grp1->gr_mem == NULL) || (grp2->gr_mem == NULL)) + goto errfin; + + for (;*c1 && *c2; ++c1, ++c2) + if (strcmp(*c1, *c2) != 0) + goto errfin; + + if ((*c1 != '\0') || (*c2 != '\0')) + goto errfin; + + return 0; + +errfin: + if ((debug) && (mdata == NULL)) { + printf("following structures are not equal:\n"); + dump_group(grp1); + dump_group(grp2); + } + + return (-1); +} + +static void +sdump_group(struct group *grp, char *buffer, size_t buflen) +{ + char **cp; + int written; + + written = snprintf(buffer, buflen, "%s %s %d", + grp->gr_name, grp->gr_passwd, grp->gr_gid); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (grp->gr_mem != NULL) { + if (*(grp->gr_mem) != '\0') { + for (cp = grp->gr_mem; *cp; ++cp) { + written = snprintf(buffer, buflen, " %s",*cp); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else + snprintf(buffer, buflen, " nomem"); + } else + snprintf(buffer, buflen, " (null)"); +} + +static int +group_read_snapshot_func(struct group *grp, char *line) +{ + StringList *sl; + char *s, *ps, *ts; + int i; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + i = 0; + sl = NULL; + ps = line; + memset(grp, 0, sizeof(struct group)); + while ( (s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + grp->gr_name = strdup(s); + assert(grp->gr_name != NULL); + break; + + case 1: + grp->gr_passwd = strdup(s); + assert(grp->gr_passwd != NULL); + break; + + case 2: + grp->gr_gid = (gid_t)strtol(s, &ts, 10); + if (*ts != '\0') { + free(grp->gr_name); + free(grp->gr_passwd); + return (-1); + } + break; + + default: + if (sl == NULL) { + if (strcmp(s, "(null)") == 0) + return (0); + + sl = sl_init(); + assert(sl != NULL); + + if (strcmp(s, "nomem") != 0) { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + } else { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + break; + }; + ++i; + } + + if (i < 3) { + free(grp->gr_name); + free(grp->gr_passwd); + memset(grp, 0, sizeof(struct group)); + return (-1); + } + + sl_add(sl, NULL); + grp->gr_mem = sl->sl_str; + + /* NOTE: is it a dirty hack or not? */ + free(sl); + return (0); +} + +static void +dump_group(struct group *result) +{ + if (result != NULL) { + char buffer[1024]; + sdump_group(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +group_fill_test_data(struct group_test_data *td) +{ + struct group *grp; + + setgroupent(1); + while ((grp = getgrent()) != NULL) { + if (group_test_correctness(grp, NULL) == 0) + TEST_DATA_APPEND(group, td, grp); + else + return (-1); + } + endgrent(); + + return (0); +} + +static int +group_test_correctness(struct group *grp, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_group(grp); + } + + if (grp == NULL) + goto errfin; + + if (grp->gr_name == NULL) + goto errfin; + + if (grp->gr_passwd == NULL) + goto errfin; + + if (grp->gr_mem == NULL) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +/* group_check_ambiguity() is needed here because when doing the getgrent() + * calls sequence, records from different nsswitch sources can be different, + * though having the same pw_name/pw_uid */ +static int +group_check_ambiguity(struct group_test_data *td, struct group *pwd) +{ + + return (TEST_DATA_FIND(group, td, pwd, compare_group, + NULL) != NULL ? 0 : -1); +} + +static int +group_test_getgrnam(struct group *grp_model, void *mdata) +{ + struct group *grp; + + if (debug) { + printf("testing getgrnam() with the following data:\n"); + dump_group(grp_model); + } + + grp = getgrnam(grp_model->gr_name); + if (group_test_correctness(grp, NULL) != 0) + goto errfin; + + if ((compare_group(grp, grp_model, NULL) != 0) && + (group_check_ambiguity((struct group_test_data *)mdata, grp) + !=0)) + goto errfin; + + if (debug) + printf("ok\n"); + return (0); + +errfin: + if (debug) + printf("not ok\n"); + + return (-1); +} + +static int +group_test_getgrgid(struct group *grp_model, void *mdata) +{ + struct group *grp; + + if (debug) { + printf("testing getgrgid() with the following data...\n"); + dump_group(grp_model); + } + + grp = getgrgid(grp_model->gr_gid); + if ((group_test_correctness(grp, NULL) != 0) || + ((compare_group(grp, grp_model, NULL) != 0) && + (group_check_ambiguity((struct group_test_data *)mdata, grp) + != 0))) { + if (debug) + printf("not ok\n"); + return (-1); + } else { + if (debug) + printf("ok\n"); + return (0); + } +} + +static int +group_test_getgrent(struct group *grp, void *mdata) +{ + /* Only correctness can be checked when doing 1-pass test for + * getgrent(). */ + return (group_test_correctness(grp, NULL)); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s -nge2 [-d] [-s <file>]\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct group_test_data td, td_snap, td_2pass; + char *snapshot_file; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + while ((c = getopt(argc, argv, "nge2ds:")) != -1) + switch (c) { + case 'd': + debug++; + break; + case 'n': + method = TEST_GETGRNAM; + break; + case 'g': + method = TEST_GETGRGID; + break; + case 'e': + method = TEST_GETGRENT; + break; + case '2': + method = TEST_GETGRENT_2PASS; + break; + case 's': + snapshot_file = strdup(optarg); + break; + default: + usage(); + } + + TEST_DATA_INIT(group, &td, clone_group, free_group); + TEST_DATA_INIT(group, &td_snap, clone_group, free_group); + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + if (method == TEST_BUILD_SNAPSHOT) { + rv = 0; + goto fin; + } + + TEST_SNAPSHOT_FILE_READ(group, snapshot_file, + &td_snap, group_read_snapshot_func); + } + } + + rv = group_fill_test_data(&td); + if (rv == -1) + return (-1); + switch (method) { + case TEST_GETGRNAM: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(group, &td, + group_test_getgrnam, (void *)&td); + else + rv = DO_1PASS_TEST(group, &td_snap, + group_test_getgrnam, (void *)&td_snap); + break; + case TEST_GETGRGID: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(group, &td, + group_test_getgrgid, (void *)&td); + else + rv = DO_1PASS_TEST(group, &td_snap, + group_test_getgrgid, (void *)&td_snap); + break; + case TEST_GETGRENT: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(group, &td, group_test_getgrent, + (void *)&td); + else + rv = DO_2PASS_TEST(group, &td, &td_snap, + compare_group, NULL); + break; + case TEST_GETGRENT_2PASS: + TEST_DATA_INIT(group, &td_2pass, clone_group, free_group); + rv = group_fill_test_data(&td_2pass); + if (rv != -1) + rv = DO_2PASS_TEST(group, &td, &td_2pass, + compare_group, NULL); + TEST_DATA_DESTROY(group, &td_2pass); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) + rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td, + sdump_group); + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(group, &td_snap); + TEST_DATA_DESTROY(group, &td); + free(snapshot_file); + return (rv); +} diff --git a/tools/regression/lib/libc/nss/test-getgr.t b/tools/regression/lib/libc/nss/test-getgr.t new file mode 100644 index 0000000..e2cf8e5 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getgr.t @@ -0,0 +1,29 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..8 +do_test 1 'getgrnam()' '-n' +do_test 2 'getgrgid()' '-g' +do_test 3 'getgrent()' '-e' +do_test 4 'getgrent() 2-pass' '-2' +do_test 5 'building snapshot, if needed' '-s snapshot_grp' +do_test 6 'getgrnam() snapshot' '-n -s snapshot_grp' +do_test 7 'getgrgid() snapshot' '-g -s snapshot_grp' +do_test 8 'getgrent() snapshot' '-e -s snapshot_grp' diff --git a/tools/regression/lib/libc/nss/test-gethostby.c b/tools/regression/lib/libc/nss/test-gethostby.c new file mode 100644 index 0000000..61e4ca2 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-gethostby.c @@ -0,0 +1,1105 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights rehted. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <assert.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stringlist.h> +#include <unistd.h> +#include "testutil.h" + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif + +enum test_methods { + TEST_GETHOSTBYNAME2, + TEST_GETHOSTBYADDR, + TEST_GETHOSTBYNAME2_GETADDRINFO, + TEST_GETHOSTBYADDR_GETNAMEINFO, + TEST_BUILD_SNAPSHOT, + TEST_BUILD_ADDR_SNAPSHOT +}; + +static int use_ipnode_functions = 0; +static int use_ipv6_mapping = 0; +static int ipnode_flags = 0; +static int debug = 0; +static int af_type = AF_INET; +static enum test_methods method = TEST_BUILD_SNAPSHOT; + +DECLARE_TEST_DATA(hostent) +DECLARE_TEST_FILE_SNAPSHOT(hostent) +DECLARE_1PASS_TEST(hostent) +DECLARE_2PASS_TEST(hostent) + +/* These stubs will use gethostby***() or getipnodeby***() functions, + * depending on the use_ipnode_functions global variable value */ +static struct hostent *__gethostbyname2(const char *, int); +static struct hostent *__gethostbyaddr(const void *, socklen_t, int); +static void __freehostent(struct hostent *); + +static void clone_hostent(struct hostent *, struct hostent const *); +static int compare_hostent(struct hostent *, struct hostent *, void *); +static void dump_hostent(struct hostent *); +static void free_hostent(struct hostent *); + +static int is_hostent_equal(struct hostent *, struct addrinfo *); + +static void sdump_hostent(struct hostent *, char *, size_t); +static int hostent_read_hostlist_func(struct hostent *, char *); +static int hostent_read_snapshot_addr(char *, unsigned char *, size_t); +static int hostent_read_snapshot_func(struct hostent *, char *); + +static int hostent_test_correctness(struct hostent *, void *); +static int hostent_test_gethostbyaddr(struct hostent *, void *); +static int hostent_test_getaddrinfo_eq(struct hostent *, void *); +static int hostent_test_getnameinfo_eq(struct hostent *, void *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(hostent) +IMPLEMENT_TEST_FILE_SNAPSHOT(hostent) +IMPLEMENT_1PASS_TEST(hostent) +IMPLEMENT_2PASS_TEST(hostent) + +static struct hostent * +__gethostbyname2(const char *name, int af) +{ + struct hostent *he; + int error; + + if (use_ipnode_functions == 0) + he = gethostbyname2(name, af); + else { + error = 0; + he = getipnodebyname(name, af, ipnode_flags, &error); + if (he == NULL); + errno = error; + } + + return (he); +} + +static struct hostent * +__gethostbyaddr(const void *addr, socklen_t len, int af) +{ + struct hostent *he; + int error; + + if (use_ipnode_functions == 0) + he = gethostbyaddr(addr, len, af); + else { + error = 0; + he = getipnodebyaddr(addr, len, af, &error); + if (he == NULL) + errno = error; + } + + return (he); +} + +static void +__freehostent(struct hostent *he) +{ + /* NOTE: checking for he != NULL - just in case */ + if ((use_ipnode_functions != 0) && (he != NULL)) + freehostent(he); +} + +static void +clone_hostent(struct hostent *dest, struct hostent const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + char **cp; + int aliases_num; + int addrs_num; + size_t offset; + + memset(dest, 0, sizeof(struct hostent)); + + if (src->h_name != NULL) { + dest->h_name = strdup(src->h_name); + assert(dest->h_name != NULL); + } + + dest->h_addrtype = src->h_addrtype; + dest->h_length = src->h_length; + + if (src->h_aliases != NULL) { + aliases_num = 0; + for (cp = src->h_aliases; *cp; ++cp) + ++aliases_num; + + dest->h_aliases = (char **)malloc((aliases_num + 1) * + (sizeof(char *))); + assert(dest->h_aliases != NULL); + memset(dest->h_aliases, 0, (aliases_num + 1) * + (sizeof(char *))); + + for (cp = src->h_aliases; *cp; ++cp) { + dest->h_aliases[cp - src->h_aliases] = strdup(*cp); + assert(dest->h_aliases[cp - src->h_aliases] != NULL); + } + } + + if (src->h_addr_list != NULL) { + addrs_num = 0; + for (cp = src->h_addr_list; *cp; ++cp) + ++addrs_num; + + dest->h_addr_list = (char **)malloc((addrs_num + 1) * + (sizeof(char *))); + assert(dest->h_addr_list != NULL); + memset(dest->h_addr_list, 0, (addrs_num + 1) * + (sizeof(char *))); + + for (cp = src->h_addr_list; *cp; ++cp) { + offset = cp - src->h_addr_list; + dest->h_addr_list[offset] = + (char *)malloc(src->h_length); + assert(dest->h_addr_list[offset] != NULL); + memcpy(dest->h_addr_list[offset], + src->h_addr_list[offset], src->h_length); + } + } +} + +static void +free_hostent(struct hostent *ht) +{ + char **cp; + + assert(ht != NULL); + + free(ht->h_name); + + if (ht->h_aliases != NULL) { + for (cp = ht->h_aliases; *cp; ++cp) + free(*cp); + free(ht->h_aliases); + } + + if (ht->h_addr_list != NULL) { + for (cp = ht->h_addr_list; *cp; ++cp) + free(*cp); + free(ht->h_addr_list); + } +} + +static int +compare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata) +{ + char **c1, **c2, **ct, **cb; + int b; + + if (ht1 == ht2) + return 0; + + if ((ht1 == NULL) || (ht2 == NULL)) + goto errfin; + + if ((ht1->h_name == NULL) || (ht2->h_name == NULL)) + goto errfin; + + if ((ht1->h_addrtype != ht2->h_addrtype) || + (ht1->h_length != ht2->h_length) || + (strcmp(ht1->h_name, ht2->h_name) != 0)) + goto errfin; + + c1 = ht1->h_aliases; + c2 = ht2->h_aliases; + + if (((ht1->h_aliases == NULL) || (ht2->h_aliases == NULL)) && + (ht1->h_aliases != ht2->h_aliases)) + goto errfin; + + if ((c1 != NULL) && (c2 != NULL)) { + cb = c1; + for (;*c1; ++c1) { + b = 0; + for (ct = c2; *ct; ++ct) { + if (strcmp(*c1, *ct) == 0) { + b = 1; + break; + } + } + if (b == 0) { + if (debug) + printf("h1 aliases item can't be "\ + "found in h2 aliases\n"); + goto errfin; + } + } + + c1 = cb; + for (;*c2; ++c2) { + b = 0; + for (ct = c1; *ct; ++ct) { + if (strcmp(*c2, *ct) == 0) { + b = 1; + break; + } + } + if (b == 0) { + if (debug) + printf("h2 aliases item can't be "\ + " found in h1 aliases\n"); + goto errfin; + } + } + } + + c1 = ht1->h_addr_list; + c2 = ht2->h_addr_list; + + if (((ht1->h_addr_list == NULL) || (ht2->h_addr_list== NULL)) && + (ht1->h_addr_list != ht2->h_addr_list)) + goto errfin; + + if ((c1 != NULL) && (c2 != NULL)) { + cb = c1; + for (;*c1; ++c1) { + b = 0; + for (ct = c2; *ct; ++ct) { + if (memcmp(*c1, *ct, ht1->h_length) == 0) { + b = 1; + break; + } + } + if (b == 0) { + if (debug) + printf("h1 addresses item can't be "\ + "found in h2 addresses\n"); + goto errfin; + } + } + + c1 = cb; + for (;*c2; ++c2) { + b = 0; + for (ct = c1; *ct; ++ct) { + if (memcmp(*c2, *ct, ht1->h_length) == 0) { + b = 1; + break; + } + } + if (b == 0) { + if (debug) + printf("h2 addresses item can't be "\ + "found in h1 addresses\n"); + goto errfin; + } + } + } + + return 0; + +errfin: + if ((debug) && (mdata == NULL)) { + printf("following structures are not equal:\n"); + dump_hostent(ht1); + dump_hostent(ht2); + } + + return (-1); +} + +static int +check_addrinfo_for_name(struct addrinfo *ai, char const *name) +{ + struct addrinfo *ai2; + + for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) { + if (strcmp(ai2->ai_canonname, name) == 0) + return (0); + } + + return (-1); +} + +static int +check_addrinfo_for_addr(struct addrinfo *ai, char const *addr, + socklen_t addrlen, int af) +{ + struct addrinfo *ai2; + + for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) { + if (af != ai2->ai_family) + continue; + + switch (af) { + case AF_INET: + if (memcmp(addr, + (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr, + min(addrlen, ai2->ai_addrlen)) == 0) + return (0); + break; + case AF_INET6: + if (memcmp(addr, + (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr, + min(addrlen, ai2->ai_addrlen)) == 0) + return (0); + break; + default: + break; + } + } + + return (-1); +} + +static int +is_hostent_equal(struct hostent *he, struct addrinfo *ai) +{ + char **cp; + int rv; + + if (debug) + printf("checking equality of he and ai\n"); + + rv = check_addrinfo_for_name(ai, he->h_name); + if (rv != 0) { + if (debug) + printf("not equal - he->h_name couldn't be found\n"); + + return (rv); + } + + for (cp = he->h_addr_list; *cp; ++cp) { + rv = check_addrinfo_for_addr(ai, *cp, he->h_length, + he->h_addrtype); + if (rv != 0) { + if (debug) + printf("not equal - one of he->h_addr_list couldn't be found\n"); + + return (rv); + } + } + + if (debug) + printf("equal\n"); + + return (0); +} + +static void +sdump_hostent(struct hostent *ht, char *buffer, size_t buflen) +{ + char **cp; + size_t i; + int written; + + written = snprintf(buffer, buflen, "%s %d %d", + ht->h_name, ht->h_addrtype, ht->h_length); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (ht->h_aliases != NULL) { + if (*(ht->h_aliases) != NULL) { + for (cp = ht->h_aliases; *cp; ++cp) { + written = snprintf(buffer, buflen, " %s",*cp); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else { + written = snprintf(buffer, buflen, " noaliases"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + } else { + written = snprintf(buffer, buflen, " (null)"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + + written = snprintf(buffer, buflen, " : "); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (ht->h_addr_list != NULL) { + if (*(ht->h_addr_list) != NULL) { + for (cp = ht->h_addr_list; *cp; ++cp) { + for (i = 0; i < ht->h_length; ++i ) { + written = snprintf(buffer, buflen, + i + 1 != ht->h_length ? "%d." : "%d", + (unsigned char)(*cp)[i]); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + + if (*(cp + 1) ) { + written = snprintf(buffer, buflen, " "); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + } + } else { + written = snprintf(buffer, buflen, " noaddrs"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + } else { + written = snprintf(buffer, buflen, " (null)"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } +} + +static int +hostent_read_hostlist_func(struct hostent *he, char *line) +{ + struct hostent *result; + int rv; + + if (debug) + printf("resolving %s: ", line); + result = __gethostbyname2(line, af_type); + if (result != NULL) { + if (debug) + printf("found\n"); + + rv = hostent_test_correctness(result, NULL); + if (rv != 0) { + __freehostent(result); + return (rv); + } + + clone_hostent(he, result); + __freehostent(result); + } else { + if (debug) + printf("not found\n"); + + memset(he, 0, sizeof(struct hostent)); + he->h_name = strdup(line); + assert(he->h_name != NULL); + } + return (0); +} + +static int +hostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len) +{ + char *s, *ps, *ts; + + ps = addr; + while ( (s = strsep(&ps, ".")) != NULL) { + if (len == 0) + return (-1); + + *result = (unsigned char)strtol(s, &ts, 10); + ++result; + if (*ts != '\0') + return (-1); + + --len; + } + if (len != 0) + return (-1); + else + return (0); +} + +static int +hostent_read_snapshot_func(struct hostent *ht, char *line) +{ + StringList *sl1, *sl2;; + char *s, *ps, *ts; + int i, rv; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + rv = 0; + i = 0; + sl1 = sl2 = NULL; + ps = line; + memset(ht, 0, sizeof(struct hostent)); + while ( (s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + ht->h_name = strdup(s); + assert(ht->h_name != NULL); + break; + + case 1: + ht->h_addrtype = (int)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + + case 2: + ht->h_length = (int)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + + case 3: + if (sl1 == NULL) { + if (strcmp(s, "(null)") == 0) + return (0); + + sl1 = sl_init(); + assert(sl1 != NULL); + + if (strcmp(s, "noaliases") != 0) { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl1, ts); + } + } else { + if (strcmp(s, ":") == 0) + ++i; + else { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl1, ts); + } + } + break; + + case 4: + if (sl2 == NULL) { + if (strcmp(s, "(null)") == 0) + return (0); + + sl2 = sl_init(); + assert(sl2 != NULL); + + if (strcmp(s, "noaddrs") != 0) { + ts = (char *)malloc(ht->h_length); + assert(ts != NULL); + memset(ts, 0, ht->h_length); + rv = hostent_read_snapshot_addr(s,\ + (unsigned char *)ts, ht->h_length); + sl_add(sl2, ts); + if (rv != 0) + goto fin; + } + } else { + ts = (char *)malloc(ht->h_length); + assert(ts != NULL); + memset(ts, 0, ht->h_length); + rv = hostent_read_snapshot_addr(s,\ + (unsigned char *)ts, ht->h_length); + sl_add(sl2, ts); + if (rv != 0) + goto fin; + } + break; + default: + break; + }; + + if ((i != 3) && (i != 4)) + ++i; + } + +fin: + if (sl1 != NULL) { + sl_add(sl1, NULL); + ht->h_aliases = sl1->sl_str; + } + if (sl2 != NULL) { + sl_add(sl2, NULL); + ht->h_addr_list = sl2->sl_str; + } + + if ((i != 4) || (rv != 0)) { + free_hostent(ht); + memset(ht, 0, sizeof(struct hostent)); + return (-1); + } + + /* NOTE: is it a dirty hack or not? */ + free(sl1); + free(sl2); + return (0); +} + +static void +dump_hostent(struct hostent *result) +{ + if (result != NULL) { + char buffer[1024]; + sdump_hostent(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +hostent_test_correctness(struct hostent *ht, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_hostent(ht); + } + + if (ht == NULL) + goto errfin; + + if (ht->h_name == NULL) + goto errfin; + + if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX))) + goto errfin; + + if ((ht->h_length != sizeof(struct in_addr)) && + (ht->h_length != sizeof(struct in6_addr))) + goto errfin; + + if (ht->h_aliases == NULL) + goto errfin; + + if (ht->h_addr_list == NULL) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +static int +hostent_test_gethostbyaddr(struct hostent *he, void *mdata) +{ + struct hostent *result; + struct hostent_test_data *addr_test_data; + int rv; + + addr_test_data = (struct hostent_test_data *)mdata; + + /* We should omit unresolved hostents */ + if (he->h_addr_list != NULL) { + char **cp; + for (cp = he->h_addr_list; *cp; ++cp) { + if (debug) + printf("doing reverse lookup for %s\n", he->h_name); + + result = __gethostbyaddr(*cp, he->h_length, + he->h_addrtype); + if (result == NULL) { + if (debug) + printf("warning: reverse lookup failed\n"); + + continue; + } + rv = hostent_test_correctness(result, NULL); + if (rv != 0) { + __freehostent(result); + return (rv); + } + + if (addr_test_data != NULL) + TEST_DATA_APPEND(hostent, addr_test_data, result); + + __freehostent(result); + } + } + + return (0); +} + +static int +hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata) +{ + struct addrinfo *ai, hints; + int rv; + + ai = NULL; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = af_type; + hints.ai_flags = AI_CANONNAME; + + if (debug) + printf("using getaddrinfo() to resolve %s\n", he->h_name); + + /* struct hostent *he was not resolved */ + if (he->h_addr_list == NULL) { + /* We can be sure that he->h_name is not NULL */ + rv = getaddrinfo(he->h_name, NULL, &hints, &ai); + if (rv == 0) { + if (debug) + printf("not ok - shouldn't have been resolved\n"); + return (-1); + } + } else { + rv = getaddrinfo(he->h_name, NULL, &hints, &ai); + if (rv != 0) { + if (debug) + printf("not ok - should have beed resolved\n"); + return (-1); + } + + rv = is_hostent_equal(he, ai); + if (rv != 0) { + if (debug) + printf("not ok - addrinfo and hostent are not equal\n"); + return (-1); + } + + } + + return (0); +} + +static int +hostent_test_getnameinfo_eq(struct hostent *he, void *mdata) +{ + char buffer[NI_MAXHOST]; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *saddr; + struct hostent *result; + int rv; + + if (he->h_addr_list != NULL) { + char **cp; + for (cp = he->h_addr_list; *cp; ++cp) { + if (debug) + printf("doing reverse lookup for %s\n", he->h_name); + + result = __gethostbyaddr(*cp, he->h_length, + he->h_addrtype); + if (result != NULL) { + rv = hostent_test_correctness(result, NULL); + if (rv != 0) { + __freehostent(result); + return (rv); + } + } else { + if (debug) + printf("reverse lookup failed\n"); + } + + switch (he->h_addrtype) { + case AF_INET: + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_len = sizeof(struct sockaddr_in); + sin.sin_family = AF_INET; + memcpy(&sin.sin_addr, *cp, he->h_length); + + saddr = (struct sockaddr *)&sin; + break; + case AF_INET6: + memset(&sin6, 0, sizeof(struct sockaddr_in6)); + sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_family = AF_INET6; + memcpy(&sin6.sin6_addr, *cp, he->h_length); + + saddr = (struct sockaddr *)&sin6; + break; + default: + if (debug) + printf("warning: %d family is unsupported\n", + he->h_addrtype); + continue; + } + + assert(saddr != NULL); + rv = getnameinfo(saddr, saddr->sa_len, buffer, + sizeof(buffer), NULL, 0, NI_NAMEREQD); + + if ((rv != 0) && (result != NULL)) { + if (debug) + printf("not ok - getnameinfo() didn't make the reverse lookup, when it should have (%s)\n", + gai_strerror(rv)); + return (rv); + } + + if ((rv == 0) && (result == NULL)) { + if (debug) + printf("not ok - getnameinfo() made the reverse lookup, when it shouldn't have\n"); + return (rv); + } + + if ((rv != 0) && (result == NULL)) { + if (debug) + printf("ok - both getnameinfo() and ***byaddr() failed\n"); + + continue; + } + + if (debug) + printf("comparing %s with %s\n", result->h_name, + buffer); + + rv = strcmp(result->h_name, buffer); + __freehostent(result); + + if (rv != 0) { + if (debug) + printf("not ok - getnameinfo() and ***byaddr() results are not equal\n"); + return (rv); + } else { + if (debug) + printf("ok - getnameinfo() and ***byaddr() results are equal\n"); + } + } + } + + return (0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s -na2i [-o] [-d] [-46] [-mAcM] [-C] [-s <file>] -f <file>\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct hostent_test_data td, td_addr, td_snap; + char *snapshot_file, *hostlist_file; + res_state statp; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + hostlist_file = NULL; + while ((c = getopt(argc, argv, "nad2iod46mAcMs:f:")) != -1) + switch (c) { + case '4': + af_type = AF_INET; + break; + case '6': + af_type = AF_INET6; + break; + case 'M': + af_type = AF_INET6; + use_ipv6_mapping = 1; + ipnode_flags |= AI_V4MAPPED_CFG; + break; + case 'm': + af_type = AF_INET6; + use_ipv6_mapping = 1; + ipnode_flags |= AI_V4MAPPED; + break; + case 'c': + ipnode_flags |= AI_ADDRCONFIG; + break; + case 'A': + ipnode_flags |= AI_ALL; + break; + case 'o': + use_ipnode_functions = 1; + break; + case 'd': + debug = 1; + break; + case 'n': + method = TEST_GETHOSTBYNAME2; + break; + case 'a': + method = TEST_GETHOSTBYADDR; + break; + case '2': + method = TEST_GETHOSTBYNAME2_GETADDRINFO; + break; + case 'i': + method = TEST_GETHOSTBYADDR_GETNAMEINFO; + break; + case 's': + snapshot_file = strdup(optarg); + break; + case 'f': + hostlist_file = strdup(optarg); + break; + default: + usage(); + } + + if (use_ipnode_functions == 0) { + statp = __res_state(); + if ((statp == NULL) || ((statp->options & RES_INIT) == 0 && + res_ninit(statp) == -1)) { + if (debug) + printf("error: can't init res_state\n"); + + free(snapshot_file); + free(hostlist_file); + return (-1); + } + + if (use_ipv6_mapping == 0) + statp->options &= ~RES_USE_INET6; + else + statp->options |= RES_USE_INET6; + } + + TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent); + TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent); + TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent); + + if (hostlist_file == NULL) + usage(); + + if (access(hostlist_file, R_OK) != 0) { + if (debug) + printf("can't access the hostlist file %s\n", + hostlist_file); + + usage(); + } + + if (debug) + printf("building host lists from %s\n", hostlist_file); + + rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td, + hostent_read_hostlist_func); + if (rv != 0) + goto fin; + + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) { + if (method != TEST_GETHOSTBYADDR) + method = TEST_BUILD_SNAPSHOT; + else + method = TEST_BUILD_ADDR_SNAPSHOT; + } else { + if (debug) + printf("can't access the snapshot file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file, + &td_snap, hostent_read_snapshot_func); + if (rv != 0) { + if (debug) + printf("error reading snapshot file\n"); + goto fin; + } + } + } + + switch (method) { + case TEST_GETHOSTBYNAME2: + if (snapshot_file != NULL) + rv = DO_2PASS_TEST(hostent, &td, &td_snap, + compare_hostent, NULL); + break; + case TEST_GETHOSTBYADDR: + rv = DO_1PASS_TEST(hostent, &td, + hostent_test_gethostbyaddr, (void *)&td_addr); + + if (snapshot_file != NULL) + rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap, + compare_hostent, NULL); + break; + case TEST_GETHOSTBYNAME2_GETADDRINFO: + rv = DO_1PASS_TEST(hostent, &td, + hostent_test_getaddrinfo_eq, NULL); + break; + case TEST_GETHOSTBYADDR_GETNAMEINFO: + rv = DO_1PASS_TEST(hostent, &td, + hostent_test_getnameinfo_eq, NULL); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) { + rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td, + sdump_hostent); + } + break; + case TEST_BUILD_ADDR_SNAPSHOT: + if (snapshot_file != NULL) { + rv = DO_1PASS_TEST(hostent, &td, + hostent_test_gethostbyaddr, (void *)&td_addr); + + rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, + &td_addr, sdump_hostent); + } + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(hostent, &td_snap); + TEST_DATA_DESTROY(hostent, &td_addr); + TEST_DATA_DESTROY(hostent, &td); + free(hostlist_file); + free(snapshot_file); + + return (rv); +} + diff --git a/tools/regression/lib/libc/nss/test-gethostby.t b/tools/regression/lib/libc/nss/test-gethostby.t new file mode 100644 index 0000000..42bed00 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-gethostby.t @@ -0,0 +1,113 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..46 +#Tests for gethostby***() functions +#IPv4-driven testing +do_test 1 'gethostbyname2() (IPv4)' '-4 -n -f mach' +do_test 2 'gethostbyaddr() (IPv4)' '-4 -a -f mach' +do_test 3 'gethostbyname2()-getaddrinfo() (IPv4)' '-4 -2 -f mach' +do_test 4 'gethostbyaddr()-getnameinfo() (IPv4)' '-4 -i -f mach' +do_test 5 'gethostbyname2() snapshot (IPv4)'\ + '-4 -n -s snapshot_htname4 -f mach' +do_test 6 'gethostbyaddr() snapshot (IPv4)'\ + '-4 -a -s snapshot_htaddr4 -f mach' + +#IPv6-driven testing +do_test 7 'gethostbyname2() (IPv6)' '-6 -n -f mach' +do_test 8 'gethostbyaddr() (IPv6)' '-6 -a -f mach' +do_test 9 'gethostbyname2()-getaddrinfo() (IPv6)' '-6 -2 -f mach' +do_test 10 'gethostbyaddr()-getnameinfo() (IPv6)' '-6 -i -f mach' +do_test 11 'gethostbyname2() snapshot (IPv6)'\ + '-6 -n -s snapshot_htname6 -f mach' +do_test 12 'gethostbyaddr() snapshot (IPv6)'\ + '-6 -a -s snapshot_htaddr6 -f mach' + +#Mapped IPv6-driven testing (getaddrinfo() equality test is useless here) +do_test 13 'gethostbyname2() (IPv6 mapped)' '-m -n -f mach' +do_test 14 'gethostbyaddr() (IPv6 mapped)' '-m -a -f mach' +do_test 15 'gethostbyname2() snapshot (IPv6 mapped)'\ + '-m -n -s snapshot_htname6map -f mach' +do_test 16 'gethostbyaddr() snapshot (IPv6 mapped)'\ + '-m -a -s snapshot_htaddr6map -f mach' + +#Tests for getipnodeby***() functions +#IPv4-driven testing, flags are 0 +do_test 17 'getipnodebyname() (IPv4)' '-o -4 -n -f mach' +do_test 18 'getipnodebyaddr() (IPv4)' '-o -4 -a -f mach' +do_test 19 'getipnodebyname()-getaddrinfo() (IPv4)' '-o -4 -2 -f mach' +do_test 20 'getipnodebyaddr()-getnameinfo() (IPv4)' '-o -4 -i -f mach' +do_test 21 'getipnodebyname() snapshot (IPv4)'\ + '-o -4 -n -s snapshot_ipnodename4 -f mach' +do_test 22 'getipnodebyname() snapshot (IPv4)'\ + '-o -4 -a -s snapshot_ipnodeaddr4 -f mach' + +#IPv6-driven testing, flags are 0 +do_test 23 'getipnodebyname() (IPv6)' '-o -6 -n -f mach' +do_test 24 'getipnodebyaddr() (IPv6)' '-o -6 -a -f mach' +do_test 25 'getipnodebyname()-getaddrinfo() (IPv6)' '-o -6 -2 -f mach' +do_test 26 'getipnodebyaddr()-getnameinfo() (IPv6)' '-o -6 -i -f mach' +do_test 27 'getipnodebyname() snapshot (IPv6)'\ + '-o -6 -n -s snapshot_ipnodename6 -f mach' +do_test 28 'getipnodebyaddr() snapshot (IPv6)'\ + '-o -6 -a -s snapshot_ipnodeaddr6 -f mach' + +#Mapped IPv6-driven testing, flags are AI_V4MAPPED +do_test 29 'getipnodebyname() (IPv6, AI_V4MAPPED)' '-o -m -n -f mach' +do_test 30 'getipnodebyaddr() (IPv6, AI_V4MAPPED)' '-o -m -a -f mach' +do_test 31 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED)'\ + '-o -m -n -s snapshot_ipnodename6_AI_V4MAPPED -f mach' +do_test 32 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED)'\ + '-o -m -a -s snapshot_ipnodeaddr6_AI_V4MAPPED -f mach' + +#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG +do_test 33 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG)' '-o -M -n -f mach' +do_test 34 'getipnodebyaddr() (IPv6, AI_V4MAPPED_CFG)' '-o -M -a -f mach' +do_test 35 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG)'\ + '-o -M -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG -f mach' +do_test 36 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED_CFG)'\ + '-o -M -a -s snapshot_ipnodeaddr6_AI_V4MAPPED_CFG -f mach' + +#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG | AI_ALL +do_test 37 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\ + '-o -MA -n -f mach' +do_test 38 'getipnodebyaddr() (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\ + '-o -MA -a -f mach' +do_test 39 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\ + '-o -MA -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ALL -f mach' +do_test 40 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\ + '-o -MA -a -s snapshot_ipnodeaddr6_AI_V4MAPPED_CFG_AI_ALL -f mach' + +#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG | AI_ADDRCONFIG +do_test 41 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG | AI_ADDRCONFIG)'\ + '-o -Mc -n -f mach' +do_test 42 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ADDRCONFIG)'\ + '-o -Mc -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ADDRCONFIG -f mach' + +#IPv4-driven testing, flags are AI_ADDRCONFIG +do_test 43 'getipnodebyname() (IPv4, AI_ADDRCONFIG)' '-o -4c -n -f mach' +do_test 44 'getipnodebyname() snapshot (IPv4, AI_ADDRCONFIG)'\ + '-o -4c -n -s snapshot_ipnodename4_AI_ADDRCONFIG -f mach' + +#IPv6-driven testing, flags are AI_ADDRCONFIG +do_test 45 'getipnodebyname() (IPv6, AI_ADDRCONFIG)' '-o -6c -n -f mach' +do_test 46 'getipnodebyname() snapshot (IPv6, AI_ADDRCONFIG)'\ + '-o -6c -n -s snapshot_ipnodename6_AI_ADDRCONFIG -f mach' + diff --git a/tools/regression/lib/libc/nss/test-getproto.c b/tools/regression/lib/libc/nss/test-getproto.c new file mode 100644 index 0000000..b94f204 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getproto.c @@ -0,0 +1,536 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights repeed. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stringlist.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETPROTOENT, + TEST_GETPROTOBYNAME, + TEST_GETPROTOBYNUMBER, + TEST_GETPROTOENT_2PASS, + TEST_BUILD_SNAPSHOT +}; + +static int debug = 0; +static enum test_methods method = TEST_BUILD_SNAPSHOT; + +DECLARE_TEST_DATA(protoent) +DECLARE_TEST_FILE_SNAPSHOT(protoent) +DECLARE_1PASS_TEST(protoent) +DECLARE_2PASS_TEST(protoent) + +static void clone_protoent(struct protoent *, struct protoent const *); +static int compare_protoent(struct protoent *, struct protoent *, void *); +static void dump_protoent(struct protoent *); +static void free_protoent(struct protoent *); + +static void sdump_protoent(struct protoent *, char *, size_t); +static int protoent_read_snapshot_func(struct protoent *, char *); + +static int protoent_check_ambiguity(struct protoent_test_data *, + struct protoent *); +static int protoent_fill_test_data(struct protoent_test_data *); +static int protoent_test_correctness(struct protoent *, void *); +static int protoent_test_getprotobyname(struct protoent *, void *); +static int protoent_test_getprotobynumber(struct protoent *, void *); +static int protoent_test_getprotoent(struct protoent *, void *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(protoent) +IMPLEMENT_TEST_FILE_SNAPSHOT(protoent) +IMPLEMENT_1PASS_TEST(protoent) +IMPLEMENT_2PASS_TEST(protoent) + +static void +clone_protoent(struct protoent *dest, struct protoent const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + char **cp; + int aliases_num; + + memset(dest, 0, sizeof(struct protoent)); + + if (src->p_name != NULL) { + dest->p_name = strdup(src->p_name); + assert(dest->p_name != NULL); + } + + dest->p_proto = src->p_proto; + + if (src->p_aliases != NULL) { + aliases_num = 0; + for (cp = src->p_aliases; *cp; ++cp) + ++aliases_num; + + dest->p_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *))); + assert(dest->p_aliases != NULL); + memset(dest->p_aliases, 0, (aliases_num+1) * (sizeof(char *))); + + for (cp = src->p_aliases; *cp; ++cp) { + dest->p_aliases[cp - src->p_aliases] = strdup(*cp); + assert(dest->p_aliases[cp - src->p_aliases] != NULL); + } + } +} + +static void +free_protoent(struct protoent *pe) +{ + char **cp; + + assert(pe != NULL); + + free(pe->p_name); + + for (cp = pe->p_aliases; *cp; ++cp) + free(*cp); + free(pe->p_aliases); +} + +static int +compare_protoent(struct protoent *pe1, struct protoent *pe2, void *mdata) +{ + char **c1, **c2; + + if (pe1 == pe2) + return 0; + + if ((pe1 == NULL) || (pe2 == NULL)) + goto errfin; + + if ((strcmp(pe1->p_name, pe2->p_name) != 0) || + (pe1->p_proto != pe2->p_proto)) + goto errfin; + + c1 = pe1->p_aliases; + c2 = pe2->p_aliases; + + if ((pe1->p_aliases == NULL) || (pe2->p_aliases == NULL)) + goto errfin; + + for (;*c1 && *c2; ++c1, ++c2) + if (strcmp(*c1, *c2) != 0) + goto errfin; + + if ((*c1 != '\0') || (*c2 != '\0')) + goto errfin; + + return 0; + +errfin: + if ((debug) && (mdata == NULL)) { + printf("following structures are not equal:\n"); + dump_protoent(pe1); + dump_protoent(pe2); + } + + return (-1); +} + +static void +sdump_protoent(struct protoent *pe, char *buffer, size_t buflen) +{ + char **cp; + int written; + + written = snprintf(buffer, buflen, "%s %d", + pe->p_name, pe->p_proto); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (pe->p_aliases != NULL) { + if (*(pe->p_aliases) != '\0') { + for (cp = pe->p_aliases; *cp; ++cp) { + written = snprintf(buffer, buflen, " %s",*cp); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else + snprintf(buffer, buflen, " noaliases"); + } else + snprintf(buffer, buflen, " (null)"); +} + +static int +protoent_read_snapshot_func(struct protoent *pe, char *line) +{ + StringList *sl; + char *s, *ps, *ts; + int i; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + i = 0; + sl = NULL; + ps = line; + memset(pe, 0, sizeof(struct protoent)); + while ( (s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + pe->p_name = strdup(s); + assert(pe->p_name != NULL); + break; + + case 1: + pe->p_proto = (int)strtol(s, &ts, 10); + if (*ts != '\0') { + free(pe->p_name); + return (-1); + } + break; + + default: + if (sl == NULL) { + if (strcmp(s, "(null)") == 0) + return (0); + + sl = sl_init(); + assert(sl != NULL); + + if (strcmp(s, "noaliases") != 0) { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + } else { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + break; + }; + ++i; + } + + if (i < 3) { + free(pe->p_name); + memset(pe, 0, sizeof(struct protoent)); + return (-1); + } + + sl_add(sl, NULL); + pe->p_aliases = sl->sl_str; + + /* NOTE: is it a dirty hack or not? */ + free(sl); + return (0); +} + +static void +dump_protoent(struct protoent *result) +{ + if (result != NULL) { + char buffer[1024]; + sdump_protoent(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +protoent_fill_test_data(struct protoent_test_data *td) +{ + struct protoent *pe; + + setprotoent(1); + while ((pe = getprotoent()) != NULL) { + if (protoent_test_correctness(pe, NULL) == 0) + TEST_DATA_APPEND(protoent, td, pe); + else + return (-1); + } + endprotoent(); + + return (0); +} + +static int +protoent_test_correctness(struct protoent *pe, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_protoent(pe); + } + + if (pe == NULL) + goto errfin; + + if (pe->p_name == NULL) + goto errfin; + + if (pe->p_proto < 0) + goto errfin; + + if (pe->p_aliases == NULL) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +/* protoent_check_ambiguity() is needed when one port+proto is associated with + * more than one peice (these cases are usually marked as PROBLEM in + * /etc/peices. This functions is needed also when one peice+proto is + * associated with several ports. We have to check all the protoent structures + * to make sure that pe really exists and correct */ +static int +protoent_check_ambiguity(struct protoent_test_data *td, struct protoent *pe) +{ + + return (TEST_DATA_FIND(protoent, td, pe, compare_protoent, + NULL) != NULL ? 0 : -1); +} + +static int +protoent_test_getprotobyname(struct protoent *pe_model, void *mdata) +{ + char **alias; + struct protoent *pe; + + if (debug) { + printf("testing getprotobyname() with the following data:\n"); + dump_protoent(pe_model); + } + + pe = getprotobyname(pe_model->p_name); + if (protoent_test_correctness(pe, NULL) != 0) + goto errfin; + + if ((compare_protoent(pe, pe_model, NULL) != 0) && + (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe) + !=0)) + goto errfin; + + for (alias = pe_model->p_aliases; *alias; ++alias) { + pe = getprotobyname(*alias); + + if (protoent_test_correctness(pe, NULL) != 0) + goto errfin; + + if ((compare_protoent(pe, pe_model, NULL) != 0) && + (protoent_check_ambiguity( + (struct protoent_test_data *)mdata, pe) != 0)) + goto errfin; + } + + if (debug) + printf("ok\n"); + return (0); + +errfin: + if (debug) + printf("not ok\n"); + + return (-1); +} + +static int +protoent_test_getprotobynumber(struct protoent *pe_model, void *mdata) +{ + struct protoent *pe; + + if (debug) { + printf("testing getprotobyport() with the following data...\n"); + dump_protoent(pe_model); + } + + pe = getprotobynumber(pe_model->p_proto); + if ((protoent_test_correctness(pe, NULL) != 0) || + ((compare_protoent(pe, pe_model, NULL) != 0) && + (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe) + != 0))) { + if (debug) + printf("not ok\n"); + return (-1); + } else { + if (debug) + printf("ok\n"); + return (0); + } +} + +static int +protoent_test_getprotoent(struct protoent *pe, void *mdata) +{ + /* Only correctness can be checked when doing 1-pass test for + * getprotoent(). */ + return (protoent_test_correctness(pe, NULL)); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s -nve2 [-d] [-s <file>]\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct protoent_test_data td, td_snap, td_2pass; + char *snapshot_file; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + while ((c = getopt(argc, argv, "nve2ds:")) != -1) + switch (c) { + case 'd': + debug++; + break; + case 'n': + method = TEST_GETPROTOBYNAME; + break; + case 'v': + method = TEST_GETPROTOBYNUMBER; + break; + case 'e': + method = TEST_GETPROTOENT; + break; + case '2': + method = TEST_GETPROTOENT_2PASS; + break; + case 's': + snapshot_file = strdup(optarg); + break; + default: + usage(); + } + + TEST_DATA_INIT(protoent, &td, clone_protoent, free_protoent); + TEST_DATA_INIT(protoent, &td_snap, clone_protoent, free_protoent); + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + if (method == TEST_BUILD_SNAPSHOT) { + rv = 0; + goto fin; + } + + TEST_SNAPSHOT_FILE_READ(protoent, snapshot_file, + &td_snap, protoent_read_snapshot_func); + } + } + + rv = protoent_fill_test_data(&td); + if (rv == -1) + return (-1); + switch (method) { + case TEST_GETPROTOBYNAME: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(protoent, &td, + protoent_test_getprotobyname, (void *)&td); + else + rv = DO_1PASS_TEST(protoent, &td_snap, + protoent_test_getprotobyname, (void *)&td_snap); + break; + case TEST_GETPROTOBYNUMBER: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(protoent, &td, + protoent_test_getprotobynumber, (void *)&td); + else + rv = DO_1PASS_TEST(protoent, &td_snap, + protoent_test_getprotobynumber, (void *)&td_snap); + break; + case TEST_GETPROTOENT: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(protoent, &td, + protoent_test_getprotoent, (void *)&td); + else + rv = DO_2PASS_TEST(protoent, &td, &td_snap, + compare_protoent, NULL); + break; + case TEST_GETPROTOENT_2PASS: + TEST_DATA_INIT(protoent, &td_2pass, clone_protoent, + free_protoent); + rv = protoent_fill_test_data(&td_2pass); + if (rv != -1) + rv = DO_2PASS_TEST(protoent, &td, &td_2pass, + compare_protoent, NULL); + TEST_DATA_DESTROY(protoent, &td_2pass); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) + rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file, &td, + sdump_protoent); + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(protoent, &td_snap); + TEST_DATA_DESTROY(protoent, &td); + free(snapshot_file); + return (rv); +} diff --git a/tools/regression/lib/libc/nss/test-getproto.t b/tools/regression/lib/libc/nss/test-getproto.t new file mode 100644 index 0000000..f582d31 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getproto.t @@ -0,0 +1,29 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..8 +do_test 1 'getprotobyname()' '-n' +do_test 2 'getprotobynumber()' '-v' +do_test 3 'getprotoent()' '-e' +do_test 4 'getprotoent() 2-pass' '-2' +do_test 5 'building snapshot, if needed' '-s snapshot_proto' +do_test 6 'getprotobyname() snapshot' '-n -s snapshot_proto' +do_test 7 'getprotobynumber() snapshot' '-v -s snapshot_proto' +do_test 8 'getprotoent() snapshot' '-e -s snapshot_proto' diff --git a/tools/regression/lib/libc/nss/test-getpw.c b/tools/regression/lib/libc/nss/test-getpw.c new file mode 100644 index 0000000..88277d3 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getpw.c @@ -0,0 +1,489 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights repwded. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETPWENT, + TEST_GETPWNAM, + TEST_GETPWUID, + TEST_GETPWENT_2PASS, + TEST_BUILD_SNAPSHOT +}; + +static int debug = 0; +static enum test_methods method = TEST_BUILD_SNAPSHOT; + +DECLARE_TEST_DATA(passwd) +DECLARE_TEST_FILE_SNAPSHOT(passwd) +DECLARE_1PASS_TEST(passwd) +DECLARE_2PASS_TEST(passwd) + +static void clone_passwd(struct passwd *, struct passwd const *); +static int compare_passwd(struct passwd *, struct passwd *, void *); +static void free_passwd(struct passwd *); + +static void sdump_passwd(struct passwd *, char *, size_t); +static void dump_passwd(struct passwd *); + +static int passwd_read_snapshot_func(struct passwd *, char *); + +static int passwd_check_ambiguity(struct passwd_test_data *, struct passwd *); +static int passwd_fill_test_data(struct passwd_test_data *); +static int passwd_test_correctness(struct passwd *, void *); +static int passwd_test_getpwnam(struct passwd *, void *); +static int passwd_test_getpwuid(struct passwd *, void *); +static int passwd_test_getpwent(struct passwd *, void *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(passwd) +IMPLEMENT_TEST_FILE_SNAPSHOT(passwd) +IMPLEMENT_1PASS_TEST(passwd) +IMPLEMENT_2PASS_TEST(passwd) + +static void +clone_passwd(struct passwd *dest, struct passwd const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + memcpy(dest, src, sizeof(struct passwd)); + if (src->pw_name != NULL) + dest->pw_name = strdup(src->pw_name); + if (src->pw_passwd != NULL) + dest->pw_passwd = strdup(src->pw_passwd); + if (src->pw_class != NULL) + dest->pw_class = strdup(src->pw_class); + if (src->pw_gecos != NULL) + dest->pw_gecos = strdup(src->pw_gecos); + if (src->pw_dir != NULL) + dest->pw_dir = strdup(src->pw_dir); + if (src->pw_shell != NULL) + dest->pw_shell = strdup(dest->pw_shell); +} + +static int +compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata) +{ + assert(pwd1 != NULL); + assert(pwd2 != NULL); + + if (pwd1 == pwd2) + return (0); + + if ((pwd1->pw_uid != pwd2->pw_uid) || + (pwd1->pw_gid != pwd2->pw_gid) || + (pwd1->pw_change != pwd2->pw_change) || + (pwd1->pw_expire != pwd2->pw_expire) || + (pwd1->pw_fields != pwd2->pw_fields) || + (strcmp(pwd1->pw_name, pwd2->pw_name) != 0) || + (strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0) || + (strcmp(pwd1->pw_class, pwd2->pw_class) != 0) || + (strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0) || + (strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0) || + (strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0) + ) + return (-1); + else + return (0); +} + +static void +free_passwd(struct passwd *pwd) +{ + free(pwd->pw_name); + free(pwd->pw_passwd); + free(pwd->pw_class); + free(pwd->pw_gecos); + free(pwd->pw_dir); + free(pwd->pw_shell); +} + +static void +sdump_passwd(struct passwd *pwd, char *buffer, size_t buflen) +{ + snprintf(buffer, buflen, "%s:%s:%d:%d:%d:%s:%s:%s:%s:%d:%d", + pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid, + pwd->pw_change, pwd->pw_class, pwd->pw_gecos, pwd->pw_dir, + pwd->pw_shell, pwd->pw_expire, pwd->pw_fields); +} + +static void +dump_passwd(struct passwd *pwd) +{ + if (pwd != NULL) { + char buffer[2048]; + sdump_passwd(pwd, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +passwd_read_snapshot_func(struct passwd *pwd, char *line) +{ + char *s, *ps, *ts; + int i; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + i = 0; + ps = line; + memset(pwd, 0, sizeof(struct passwd)); + while ( (s = strsep(&ps, ":")) != NULL) { + switch (i) { + case 0: + pwd->pw_name = strdup(s); + assert(pwd->pw_name != NULL); + break; + case 1: + pwd->pw_passwd = strdup(s); + assert(pwd->pw_passwd != NULL); + break; + case 2: + pwd->pw_uid = (uid_t)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + case 3: + pwd->pw_gid = (gid_t)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + case 4: + pwd->pw_change = (time_t)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + case 5: + pwd->pw_class = strdup(s); + assert(pwd->pw_class != NULL); + break; + case 6: + pwd->pw_gecos = strdup(s); + assert(pwd->pw_gecos != NULL); + break; + case 7: + pwd->pw_dir = strdup(s); + assert(pwd->pw_dir != NULL); + break; + case 8: + pwd->pw_shell = strdup(s); + assert(pwd->pw_shell != NULL); + break; + case 9: + pwd->pw_expire = (time_t)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + case 10: + pwd->pw_fields = (int)strtol(s, &ts, 10); + if (*ts != '\0') + goto fin; + break; + default: + break; + }; + ++i; + } + +fin: + if (i != 11) { + free_passwd(pwd); + memset(pwd, 0, sizeof(struct passwd)); + return (-1); + } + + return (0); +} + +static int +passwd_fill_test_data(struct passwd_test_data *td) +{ + struct passwd *pwd; + + setpassent(1); + while ((pwd = getpwent()) != NULL) { + if (passwd_test_correctness(pwd, NULL) == 0) + TEST_DATA_APPEND(passwd, td, pwd); + else + return (-1); + } + endpwent(); + + return (0); +} + +static int +passwd_test_correctness(struct passwd *pwd, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_passwd(pwd); + } + + if (pwd == NULL) + return (-1); + + if (pwd->pw_name == NULL) + goto errfin; + + if (pwd->pw_passwd == NULL) + goto errfin; + + if (pwd->pw_class == NULL) + goto errfin; + + if (pwd->pw_gecos == NULL) + goto errfin; + + if (pwd->pw_dir == NULL) + goto errfin; + + if (pwd->pw_shell == NULL) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +/* passwd_check_ambiguity() is needed here because when doing the getpwent() + * calls sequence, records from different nsswitch sources can be different, + * though having the same pw_name/pw_uid */ +static int +passwd_check_ambiguity(struct passwd_test_data *td, struct passwd *pwd) +{ + + return (TEST_DATA_FIND(passwd, td, pwd, compare_passwd, + NULL) != NULL ? 0 : -1); +} + +static int +passwd_test_getpwnam(struct passwd *pwd_model, void *mdata) +{ + struct passwd *pwd; + + if (debug) { + printf("testing getpwnam() with the following data:\n"); + dump_passwd(pwd_model); + } + + pwd = getpwnam(pwd_model->pw_name); + if (passwd_test_correctness(pwd, NULL) != 0) + goto errfin; + + if ((compare_passwd(pwd, pwd_model, NULL) != 0) && + (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd) + !=0)) + goto errfin; + + if (debug) + printf("ok\n"); + return (0); + +errfin: + if (debug) + printf("not ok\n"); + + return (-1); +} + +static int +passwd_test_getpwuid(struct passwd *pwd_model, void *mdata) +{ + struct passwd *pwd; + + if (debug) { + printf("testing getpwuid() with the following data...\n"); + dump_passwd(pwd_model); + } + + pwd = getpwuid(pwd_model->pw_uid); + if ((passwd_test_correctness(pwd, NULL) != 0) || + ((compare_passwd(pwd, pwd_model, NULL) != 0) && + (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd) + != 0))) { + if (debug) + printf("not ok\n"); + return (-1); + } else { + if (debug) + printf("ok\n"); + return (0); + } +} + +static int +passwd_test_getpwent(struct passwd *pwd, void *mdata) +{ + /* Only correctness can be checked when doing 1-pass test for + * getpwent(). */ + return (passwd_test_correctness(pwd, NULL)); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s -nue2 [-d] [-s <file>]\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct passwd_test_data td, td_snap, td_2pass; + char *snapshot_file; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + while ((c = getopt(argc, argv, "nue2ds:")) != -1) + switch (c) { + case 'd': + debug++; + break; + case 'n': + method = TEST_GETPWNAM; + break; + case 'u': + method = TEST_GETPWUID; + break; + case 'e': + method = TEST_GETPWENT; + break; + case '2': + method = TEST_GETPWENT_2PASS; + break; + case 's': + snapshot_file = strdup(optarg); + break; + default: + usage(); + } + + TEST_DATA_INIT(passwd, &td, clone_passwd, free_passwd); + TEST_DATA_INIT(passwd, &td_snap, clone_passwd, free_passwd); + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + if (method == TEST_BUILD_SNAPSHOT) { + rv = 0; + goto fin; + } + + TEST_SNAPSHOT_FILE_READ(passwd, snapshot_file, + &td_snap, passwd_read_snapshot_func); + } + } + + rv = passwd_fill_test_data(&td); + if (rv == -1) + return (-1); + + switch (method) { + case TEST_GETPWNAM: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(passwd, &td, + passwd_test_getpwnam, (void *)&td); + else + rv = DO_1PASS_TEST(passwd, &td_snap, + passwd_test_getpwnam, (void *)&td_snap); + break; + case TEST_GETPWUID: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(passwd, &td, + passwd_test_getpwuid, (void *)&td); + else + rv = DO_1PASS_TEST(passwd, &td_snap, + passwd_test_getpwuid, (void *)&td_snap); + break; + case TEST_GETPWENT: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwent, + (void *)&td); + else + rv = DO_2PASS_TEST(passwd, &td, &td_snap, + compare_passwd, NULL); + break; + case TEST_GETPWENT_2PASS: + TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd); + rv = passwd_fill_test_data(&td_2pass); + if (rv != -1) + rv = DO_2PASS_TEST(passwd, &td, &td_2pass, + compare_passwd, NULL); + TEST_DATA_DESTROY(passwd, &td_2pass); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) + rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file, &td, + sdump_passwd); + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(passwd, &td_snap); + TEST_DATA_DESTROY(passwd, &td); + free(snapshot_file); + return (rv); +} diff --git a/tools/regression/lib/libc/nss/test-getpw.t b/tools/regression/lib/libc/nss/test-getpw.t new file mode 100644 index 0000000..5172177 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getpw.t @@ -0,0 +1,29 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..8 +do_test 1 'getpwnam()' '-n' +do_test 2 'getpwuid()' '-u' +do_test 3 'getpwent()' '-e' +do_test 4 'getpwent() 2-pass' '-2' +do_test 5 'building snapshot, if needed' '-s snapshot_pwd' +do_test 6 'getpwnam() snapshot' '-n -s snapshot_pwd' +do_test 7 'getpwuid() snapshot' '-u -s snapshot_pwd' +do_test 8 'getpwent() snapshot' '-e -s snapshot_pwd' diff --git a/tools/regression/lib/libc/nss/test-getrpc.c b/tools/regression/lib/libc/nss/test-getrpc.c new file mode 100644 index 0000000..df0bc83 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getrpc.c @@ -0,0 +1,535 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights repeed. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <arpa/inet.h> +#include <rpc/rpc.h> +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stringlist.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETRPCENT, + TEST_GETRPCBYNAME, + TEST_GETRPCBYNUMBER, + TEST_GETRPCENT_2PASS, + TEST_BUILD_SNAPSHOT +}; + +static int debug = 0; +static enum test_methods method = TEST_BUILD_SNAPSHOT; + +DECLARE_TEST_DATA(rpcent) +DECLARE_TEST_FILE_SNAPSHOT(rpcent) +DECLARE_1PASS_TEST(rpcent) +DECLARE_2PASS_TEST(rpcent) + +static void clone_rpcent(struct rpcent *, struct rpcent const *); +static int compare_rpcent(struct rpcent *, struct rpcent *, void *); +static void dump_rpcent(struct rpcent *); +static void free_rpcent(struct rpcent *); + +static void sdump_rpcent(struct rpcent *, char *, size_t); +static int rpcent_read_snapshot_func(struct rpcent *, char *); + +static int rpcent_check_ambiguity(struct rpcent_test_data *, + struct rpcent *); +static int rpcent_fill_test_data(struct rpcent_test_data *); +static int rpcent_test_correctness(struct rpcent *, void *); +static int rpcent_test_getrpcbyname(struct rpcent *, void *); +static int rpcent_test_getrpcbynumber(struct rpcent *, void *); +static int rpcent_test_getrpcent(struct rpcent *, void *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(rpcent) +IMPLEMENT_TEST_FILE_SNAPSHOT(rpcent) +IMPLEMENT_1PASS_TEST(rpcent) +IMPLEMENT_2PASS_TEST(rpcent) + +static void +clone_rpcent(struct rpcent *dest, struct rpcent const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + char **cp; + int aliases_num; + + memset(dest, 0, sizeof(struct rpcent)); + + if (src->r_name != NULL) { + dest->r_name = strdup(src->r_name); + assert(dest->r_name != NULL); + } + + dest->r_number = src->r_number; + + if (src->r_aliases != NULL) { + aliases_num = 0; + for (cp = src->r_aliases; *cp; ++cp) + ++aliases_num; + + dest->r_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *))); + assert(dest->r_aliases != NULL); + memset(dest->r_aliases, 0, (aliases_num+1) * (sizeof(char *))); + + for (cp = src->r_aliases; *cp; ++cp) { + dest->r_aliases[cp - src->r_aliases] = strdup(*cp); + assert(dest->r_aliases[cp - src->r_aliases] != NULL); + } + } +} + +static void +free_rpcent(struct rpcent *rpc) +{ + char **cp; + + assert(rpc != NULL); + + free(rpc->r_name); + + for (cp = rpc->r_aliases; *cp; ++cp) + free(*cp); + free(rpc->r_aliases); +} + +static int +compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata) +{ + char **c1, **c2; + + if (rpc1 == rpc2) + return 0; + + if ((rpc1 == NULL) || (rpc2 == NULL)) + goto errfin; + + if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) || + (rpc1->r_number != rpc2->r_number)) + goto errfin; + + c1 = rpc1->r_aliases; + c2 = rpc2->r_aliases; + + if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL)) + goto errfin; + + for (;*c1 && *c2; ++c1, ++c2) + if (strcmp(*c1, *c2) != 0) + goto errfin; + + if ((*c1 != '\0') || (*c2 != '\0')) + goto errfin; + + return 0; + +errfin: + if ((debug) && (mdata == NULL)) { + printf("following structures are not equal:\n"); + dump_rpcent(rpc1); + dump_rpcent(rpc2); + } + + return (-1); +} + +static void +sdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen) +{ + char **cp; + int written; + + written = snprintf(buffer, buflen, "%s %d", + rpc->r_name, rpc->r_number); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (rpc->r_aliases != NULL) { + if (*(rpc->r_aliases) != '\0') { + for (cp = rpc->r_aliases; *cp; ++cp) { + written = snprintf(buffer, buflen, " %s",*cp); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else + snprintf(buffer, buflen, " noaliases"); + } else + snprintf(buffer, buflen, " (null)"); +} + +static int +rpcent_read_snapshot_func(struct rpcent *rpc, char *line) +{ + StringList *sl; + char *s, *ps, *ts; + int i; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + i = 0; + sl = NULL; + ps = line; + memset(rpc, 0, sizeof(struct rpcent)); + while ( (s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + rpc->r_name = strdup(s); + assert(rpc->r_name != NULL); + break; + + case 1: + rpc->r_number = (int)strtol(s, &ts, 10); + if (*ts != '\0') { + free(rpc->r_name); + return (-1); + } + break; + + default: + if (sl == NULL) { + if (strcmp(s, "(null)") == 0) + return (0); + + sl = sl_init(); + assert(sl != NULL); + + if (strcmp(s, "noaliases") != 0) { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + } else { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + break; + }; + ++i; + } + + if (i < 3) { + free(rpc->r_name); + memset(rpc, 0, sizeof(struct rpcent)); + return (-1); + } + + sl_add(sl, NULL); + rpc->r_aliases = sl->sl_str; + + /* NOTE: is it a dirty hack or not? */ + free(sl); + return (0); +} + +static void +dump_rpcent(struct rpcent *result) +{ + if (result != NULL) { + char buffer[1024]; + sdump_rpcent(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +rpcent_fill_test_data(struct rpcent_test_data *td) +{ + struct rpcent *rpc; + + setrpcent(1); + while ((rpc = getrpcent()) != NULL) { + if (rpcent_test_correctness(rpc, NULL) == 0) + TEST_DATA_APPEND(rpcent, td, rpc); + else + return (-1); + } + endrpcent(); + + return (0); +} + +static int +rpcent_test_correctness(struct rpcent *rpc, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_rpcent(rpc); + } + + if (rpc == NULL) + goto errfin; + + if (rpc->r_name == NULL) + goto errfin; + + if (rpc->r_number < 0) + goto errfin; + + if (rpc->r_aliases == NULL) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +/* rpcent_check_ambiguity() is needed when one port+rpc is associated with + * more than one peice (these cases are usually marked as PROBLEM in + * /etc/peices. This functions is needed also when one peice+rpc is + * associated with several ports. We have to check all the rpcent structures + * to make sure that rpc really exists and correct */ +static int +rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc) +{ + + return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent, + NULL) != NULL ? 0 : -1); +} + +static int +rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata) +{ + char **alias; + struct rpcent *rpc; + + if (debug) { + printf("testing getrpcbyname() with the following data:\n"); + dump_rpcent(rpc_model); + } + + rpc = getrpcbyname(rpc_model->r_name); + if (rpcent_test_correctness(rpc, NULL) != 0) + goto errfin; + + if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && + (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) + !=0)) + goto errfin; + + for (alias = rpc_model->r_aliases; *alias; ++alias) { + rpc = getrpcbyname(*alias); + + if (rpcent_test_correctness(rpc, NULL) != 0) + goto errfin; + + if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && + (rpcent_check_ambiguity( + (struct rpcent_test_data *)mdata, rpc) != 0)) + goto errfin; + } + + if (debug) + printf("ok\n"); + return (0); + +errfin: + if (debug) + printf("not ok\n"); + + return (-1); +} + +static int +rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata) +{ + struct rpcent *rpc; + + if (debug) { + printf("testing getrpcbyport() with the following data...\n"); + dump_rpcent(rpc_model); + } + + rpc = getrpcbynumber(rpc_model->r_number); + if ((rpcent_test_correctness(rpc, NULL) != 0) || + ((compare_rpcent(rpc, rpc_model, NULL) != 0) && + (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) + != 0))) { + if (debug) + printf("not ok\n"); + return (-1); + } else { + if (debug) + printf("ok\n"); + return (0); + } +} + +static int +rpcent_test_getrpcent(struct rpcent *rpc, void *mdata) +{ + /* Only correctness can be checked when doing 1-pass test for + * getrpcent(). */ + return (rpcent_test_correctness(rpc, NULL)); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s -nve2 [-d] [-s <file>]\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct rpcent_test_data td, td_snap, td_2pass; + char *snapshot_file; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + while ((c = getopt(argc, argv, "nve2ds:")) != -1) + switch (c) { + case 'd': + debug++; + break; + case 'n': + method = TEST_GETRPCBYNAME; + break; + case 'v': + method = TEST_GETRPCBYNUMBER; + break; + case 'e': + method = TEST_GETRPCENT; + break; + case '2': + method = TEST_GETRPCENT_2PASS; + break; + case 's': + snapshot_file = strdup(optarg); + break; + default: + usage(); + } + + TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent); + TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent); + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + if (method == TEST_BUILD_SNAPSHOT) { + rv = 0; + goto fin; + } + + TEST_SNAPSHOT_FILE_READ(rpcent, snapshot_file, + &td_snap, rpcent_read_snapshot_func); + } + } + + rv = rpcent_fill_test_data(&td); + if (rv == -1) + return (-1); + switch (method) { + case TEST_GETRPCBYNAME: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(rpcent, &td, + rpcent_test_getrpcbyname, (void *)&td); + else + rv = DO_1PASS_TEST(rpcent, &td_snap, + rpcent_test_getrpcbyname, (void *)&td_snap); + break; + case TEST_GETRPCBYNUMBER: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(rpcent, &td, + rpcent_test_getrpcbynumber, (void *)&td); + else + rv = DO_1PASS_TEST(rpcent, &td_snap, + rpcent_test_getrpcbynumber, (void *)&td_snap); + break; + case TEST_GETRPCENT: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent, + (void *)&td); + else + rv = DO_2PASS_TEST(rpcent, &td, &td_snap, + compare_rpcent, NULL); + break; + case TEST_GETRPCENT_2PASS: + TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent); + rv = rpcent_fill_test_data(&td_2pass); + if (rv != -1) + rv = DO_2PASS_TEST(rpcent, &td, &td_2pass, + compare_rpcent, NULL); + TEST_DATA_DESTROY(rpcent, &td_2pass); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) + rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td, + sdump_rpcent); + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(rpcent, &td_snap); + TEST_DATA_DESTROY(rpcent, &td); + free(snapshot_file); + return (rv); +} diff --git a/tools/regression/lib/libc/nss/test-getrpc.t b/tools/regression/lib/libc/nss/test-getrpc.t new file mode 100644 index 0000000..831a086 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getrpc.t @@ -0,0 +1,29 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..8 +do_test 1 'getrpcbyname()' '-n' +do_test 2 'getrpcbynumber()' '-v' +do_test 3 'getrpcent()' '-e' +do_test 4 'getrpcent() 2-pass' '-2' +do_test 5 'building snapshot, if needed' '-s snapshot_rpc' +do_test 6 'getrpcbyname() snapshot' '-n -s snapshot_rpc' +do_test 7 'getrpcbynumber() snapshot' '-v -s snapshot_rpc' +do_test 8 'getrpcent() snapshot' '-e -s snapshot_rpc' diff --git a/tools/regression/lib/libc/nss/test-getserv.c b/tools/regression/lib/libc/nss/test-getserv.c new file mode 100644 index 0000000..79d42f0 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getserv.c @@ -0,0 +1,551 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stringlist.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETSERVENT, + TEST_GETSERVBYNAME, + TEST_GETSERVBYPORT, + TEST_GETSERVENT_2PASS, + TEST_BUILD_SNAPSHOT +}; + +static int debug = 0; +static enum test_methods method = TEST_BUILD_SNAPSHOT; + +DECLARE_TEST_DATA(servent) +DECLARE_TEST_FILE_SNAPSHOT(servent) +DECLARE_1PASS_TEST(servent) +DECLARE_2PASS_TEST(servent) + +static void clone_servent(struct servent *, struct servent const *); +static int compare_servent(struct servent *, struct servent *, void *); +static void dump_servent(struct servent *); +static void free_servent(struct servent *); + +static void sdump_servent(struct servent *, char *, size_t); +static int servent_read_snapshot_func(struct servent *, char *); + +static int servent_check_ambiguity(struct servent_test_data *, + struct servent *); +static int servent_fill_test_data(struct servent_test_data *); +static int servent_test_correctness(struct servent *, void *); +static int servent_test_getservbyname(struct servent *, void *); +static int servent_test_getservbyport(struct servent *, void *); +static int servent_test_getservent(struct servent *, void *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(servent) +IMPLEMENT_TEST_FILE_SNAPSHOT(servent) +IMPLEMENT_1PASS_TEST(servent) +IMPLEMENT_2PASS_TEST(servent) + +static void +clone_servent(struct servent *dest, struct servent const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + char **cp; + int aliases_num; + + memset(dest, 0, sizeof(struct servent)); + + if (src->s_name != NULL) { + dest->s_name = strdup(src->s_name); + assert(dest->s_name != NULL); + } + + if (src->s_proto != NULL) { + dest->s_proto = strdup(src->s_proto); + assert(dest->s_proto != NULL); + } + dest->s_port = src->s_port; + + if (src->s_aliases != NULL) { + aliases_num = 0; + for (cp = src->s_aliases; *cp; ++cp) + ++aliases_num; + + dest->s_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *))); + assert(dest->s_aliases != NULL); + memset(dest->s_aliases, 0, (aliases_num+1) * (sizeof(char *))); + + for (cp = src->s_aliases; *cp; ++cp) { + dest->s_aliases[cp - src->s_aliases] = strdup(*cp); + assert(dest->s_aliases[cp - src->s_aliases] != NULL); + } + } +} + +static void +free_servent(struct servent *serv) +{ + char **cp; + + assert(serv != NULL); + + free(serv->s_name); + free(serv->s_proto); + + for (cp = serv->s_aliases; *cp; ++cp) + free(*cp); + free(serv->s_aliases); +} + +static int +compare_servent(struct servent *serv1, struct servent *serv2, void *mdata) +{ + char **c1, **c2; + + if (serv1 == serv2) + return 0; + + if ((serv1 == NULL) || (serv2 == NULL)) + goto errfin; + + if ((strcmp(serv1->s_name, serv2->s_name) != 0) || + (strcmp(serv1->s_proto, serv2->s_proto) != 0) || + (serv1->s_port != serv2->s_port)) + goto errfin; + + c1 = serv1->s_aliases; + c2 = serv2->s_aliases; + + if ((serv1->s_aliases == NULL) || (serv2->s_aliases == NULL)) + goto errfin; + + for (;*c1 && *c2; ++c1, ++c2) + if (strcmp(*c1, *c2) != 0) + goto errfin; + + if ((*c1 != '\0') || (*c2 != '\0')) + goto errfin; + + return 0; + +errfin: + if ((debug) && (mdata == NULL)) { + printf("following structures are not equal:\n"); + dump_servent(serv1); + dump_servent(serv2); + } + + return (-1); +} + +static void +sdump_servent(struct servent *serv, char *buffer, size_t buflen) +{ + char **cp; + int written; + + written = snprintf(buffer, buflen, "%s %d %s", + serv->s_name, ntohs(serv->s_port), serv->s_proto); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (serv->s_aliases != NULL) { + if (*(serv->s_aliases) != '\0') { + for (cp = serv->s_aliases; *cp; ++cp) { + written = snprintf(buffer, buflen, " %s",*cp); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else + snprintf(buffer, buflen, " noaliases"); + } else + snprintf(buffer, buflen, " (null)"); +} + +static int +servent_read_snapshot_func(struct servent *serv, char *line) +{ + StringList *sl; + char *s, *ps, *ts; + int i; + + if (debug) + printf("1 line read from snapshot:\n%s\n", line); + + i = 0; + sl = NULL; + ps = line; + memset(serv, 0, sizeof(struct servent)); + while ( (s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + serv->s_name = strdup(s); + assert(serv->s_name != NULL); + break; + + case 1: + serv->s_port = htons( + (int)strtol(s, &ts, 10)); + if (*ts != '\0') { + free(serv->s_name); + return (-1); + } + break; + + case 2: + serv->s_proto = strdup(s); + assert(serv->s_proto != NULL); + break; + + default: + if (sl == NULL) { + if (strcmp(s, "(null)") == 0) + return (0); + + sl = sl_init(); + assert(sl != NULL); + + if (strcmp(s, "noaliases") != 0) { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + } else { + ts = strdup(s); + assert(ts != NULL); + sl_add(sl, ts); + } + break; + }; + ++i; + } + + if (i < 3) { + free(serv->s_name); + free(serv->s_proto); + memset(serv, 0, sizeof(struct servent)); + return (-1); + } + + sl_add(sl, NULL); + serv->s_aliases = sl->sl_str; + + /* NOTE: is it a dirty hack or not? */ + free(sl); + return (0); +} + +static void +dump_servent(struct servent *result) +{ + if (result != NULL) { + char buffer[1024]; + sdump_servent(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +servent_fill_test_data(struct servent_test_data *td) +{ + struct servent *serv; + + setservent(1); + while ((serv = getservent()) != NULL) { + if (servent_test_correctness(serv, NULL) == 0) + TEST_DATA_APPEND(servent, td, serv); + else + return (-1); + } + endservent(); + + return (0); +} + +static int +servent_test_correctness(struct servent *serv, void *mdata) +{ + if (debug) { + printf("testing correctness with the following data:\n"); + dump_servent(serv); + } + + if (serv == NULL) + goto errfin; + + if (serv->s_name == NULL) + goto errfin; + + if (serv->s_proto == NULL) + goto errfin; + + if (ntohs(serv->s_port < 0)) + goto errfin; + + if (serv->s_aliases == NULL) + goto errfin; + + if (debug) + printf("correct\n"); + + return (0); +errfin: + if (debug) + printf("incorrect\n"); + + return (-1); +} + +/* servent_check_ambiguity() is needed when one port+proto is associated with + * more than one service (these cases are usually marked as PROBLEM in + * /etc/services. This functions is needed also when one service+proto is + * associated with several ports. We have to check all the servent structures + * to make sure that serv really exists and correct */ +static int +servent_check_ambiguity(struct servent_test_data *td, struct servent *serv) +{ + + return (TEST_DATA_FIND(servent, td, serv, compare_servent, + NULL) != NULL ? 0 : -1); +} + +static int +servent_test_getservbyname(struct servent *serv_model, void *mdata) +{ + char **alias; + struct servent *serv; + + if (debug) { + printf("testing getservbyname() with the following data:\n"); + dump_servent(serv_model); + } + + serv = getservbyname(serv_model->s_name, serv_model->s_proto); + if (servent_test_correctness(serv, NULL) != 0) + goto errfin; + + if ((compare_servent(serv, serv_model, NULL) != 0) && + (servent_check_ambiguity((struct servent_test_data *)mdata, serv) + !=0)) + goto errfin; + + for (alias = serv_model->s_aliases; *alias; ++alias) { + serv = getservbyname(*alias, serv_model->s_proto); + + if (servent_test_correctness(serv, NULL) != 0) + goto errfin; + + if ((compare_servent(serv, serv_model, NULL) != 0) && + (servent_check_ambiguity( + (struct servent_test_data *)mdata, serv) != 0)) + goto errfin; + } + + if (debug) + printf("ok\n"); + return (0); + +errfin: + if (debug) + printf("not ok\n"); + + return (-1); +} + +static int +servent_test_getservbyport(struct servent *serv_model, void *mdata) +{ + struct servent *serv; + + if (debug) { + printf("testing getservbyport() with the following data...\n"); + dump_servent(serv_model); + } + + serv = getservbyport(serv_model->s_port, serv_model->s_proto); + if ((servent_test_correctness(serv, NULL) != 0) || + ((compare_servent(serv, serv_model, NULL) != 0) && + (servent_check_ambiguity((struct servent_test_data *)mdata, serv) + != 0))) { + if (debug) + printf("not ok\n"); + return (-1); + } else { + if (debug) + printf("ok\n"); + return (0); + } +} + +static int +servent_test_getservent(struct servent *serv, void *mdata) +{ + /* Only correctness can be checked when doing 1-pass test for + * getservent(). */ + return (servent_test_correctness(serv, NULL)); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s -npe2 [-d] [-s <file>]\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct servent_test_data td, td_snap, td_2pass; + char *snapshot_file; + int rv; + int c; + + if (argc < 2) + usage(); + + snapshot_file = NULL; + while ((c = getopt(argc, argv, "npe2ds:")) != -1) + switch (c) { + case 'd': + debug++; + break; + case 'n': + method = TEST_GETSERVBYNAME; + break; + case 'p': + method = TEST_GETSERVBYPORT; + break; + case 'e': + method = TEST_GETSERVENT; + break; + case '2': + method = TEST_GETSERVENT_2PASS; + break; + case 's': + snapshot_file = strdup(optarg); + break; + default: + usage(); + } + + TEST_DATA_INIT(servent, &td, clone_servent, free_servent); + TEST_DATA_INIT(servent, &td_snap, clone_servent, free_servent); + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + if (method == TEST_BUILD_SNAPSHOT) { + rv = 0; + goto fin; + } + + TEST_SNAPSHOT_FILE_READ(servent, snapshot_file, + &td_snap, servent_read_snapshot_func); + } + } + + rv = servent_fill_test_data(&td); + if (rv == -1) + return (-1); + switch (method) { + case TEST_GETSERVBYNAME: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(servent, &td, + servent_test_getservbyname, (void *)&td); + else + rv = DO_1PASS_TEST(servent, &td_snap, + servent_test_getservbyname, (void *)&td_snap); + break; + case TEST_GETSERVBYPORT: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(servent, &td, + servent_test_getservbyport, (void *)&td); + else + rv = DO_1PASS_TEST(servent, &td_snap, + servent_test_getservbyport, (void *)&td_snap); + break; + case TEST_GETSERVENT: + if (snapshot_file == NULL) + rv = DO_1PASS_TEST(servent, &td, servent_test_getservent, + (void *)&td); + else + rv = DO_2PASS_TEST(servent, &td, &td_snap, + compare_servent, NULL); + break; + case TEST_GETSERVENT_2PASS: + TEST_DATA_INIT(servent, &td_2pass, clone_servent, free_servent); + rv = servent_fill_test_data(&td_2pass); + if (rv != -1) + rv = DO_2PASS_TEST(servent, &td, &td_2pass, + compare_servent, NULL); + TEST_DATA_DESTROY(servent, &td_2pass); + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) + rv = TEST_SNAPSHOT_FILE_WRITE(servent, snapshot_file, &td, + sdump_servent); + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(servent, &td_snap); + TEST_DATA_DESTROY(servent, &td); + free(snapshot_file); + return (rv); +} diff --git a/tools/regression/lib/libc/nss/test-getserv.t b/tools/regression/lib/libc/nss/test-getserv.t new file mode 100644 index 0000000..60a6c50 --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getserv.t @@ -0,0 +1,29 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..8 +do_test 1 'getservbyname()' '-n' +do_test 2 'getservbyport()' '-p' +do_test 3 'getservent()' '-e' +do_test 4 'getservent() 2-pass' '-2' +do_test 5 'building snapshot, if needed' '-s snapshot_serv' +do_test 6 'getservbyname() snapshot' '-n -s snapshot_serv' +do_test 7 'getservbyport() snapshot' '-p -s snapshot_serv' +do_test 8 'getservent() snapshot' '-e -s snapshot_serv' diff --git a/tools/regression/lib/libc/nss/test-getusershell.c b/tools/regression/lib/libc/nss/test-getusershell.c new file mode 100644 index 0000000..20faaac --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getusershell.c @@ -0,0 +1,235 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights repwded. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "testutil.h" + +enum test_methods { + TEST_GETUSERSHELL, + TEST_BUILD_SNAPSHOT +}; + +struct usershell { + char *path; +}; + +static int debug = 0; +static enum test_methods method = TEST_GETUSERSHELL; + +DECLARE_TEST_DATA(usershell) +DECLARE_TEST_FILE_SNAPSHOT(usershell) +DECLARE_2PASS_TEST(usershell) + +static void clone_usershell(struct usershell *, struct usershell const *); +static int compare_usershell(struct usershell *, struct usershell *, void *); +static void free_usershell(struct usershell *); + +static void sdump_usershell(struct usershell *, char *, size_t); +static void dump_usershell(struct usershell *); + +static int usershell_read_snapshot_func(struct usershell *, char *); + +static void usage(void) __attribute__((__noreturn__)); + +IMPLEMENT_TEST_DATA(usershell) +IMPLEMENT_TEST_FILE_SNAPSHOT(usershell) +IMPLEMENT_2PASS_TEST(usershell) + +static void +clone_usershell(struct usershell *dest, struct usershell const *src) +{ + assert(dest != NULL); + assert(src != NULL); + + if (src->path != NULL) { + dest->path = strdup(src->path); + assert(dest->path != NULL); + } +} + +static int +compare_usershell(struct usershell *us1, struct usershell *us2, void *mdata) +{ + int rv; + + assert(us1 != NULL); + assert(us2 != NULL); + + dump_usershell(us1); + dump_usershell(us2); + + if (us1 == us2) + return (0); + + rv = strcmp(us1->path, us2->path); + if (rv != 0) { + printf("following structures are not equal:\n"); + dump_usershell(us1); + dump_usershell(us2); + } + + return (rv); +} + +static void +free_usershell(struct usershell *us) +{ + free(us->path); +} + +static void +sdump_usershell(struct usershell *us, char *buffer, size_t buflen) +{ + snprintf(buffer, buflen, "%s", us->path); +} + +static void +dump_usershell(struct usershell *us) +{ + if (us != NULL) { + char buffer[2048]; + sdump_usershell(us, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +usershell_read_snapshot_func(struct usershell *us, char *line) +{ + us->path = strdup(line); + assert(us->path != NULL); + + return (0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s [-d] -s <file>\n", + getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct usershell_test_data td, td_snap; + struct usershell ushell; + char *snapshot_file; + int rv; + int c; + + if (argc < 2) + usage(); + + rv = 0; + snapshot_file = NULL; + while ((c = getopt(argc, argv, "ds:")) != -1) { + switch (c) { + case 'd': + debug = 1; + break; + case 's': + snapshot_file = strdup(optarg); + break; + default: + usage(); + } + } + + TEST_DATA_INIT(usershell, &td, clone_usershell, free_usershell); + TEST_DATA_INIT(usershell, &td_snap, clone_usershell, free_usershell); + + setusershell(); + while ((ushell.path = getusershell()) != NULL) { + if (debug) { + printf("usershell found:\n"); + dump_usershell(&ushell); + } + TEST_DATA_APPEND(usershell, &td, &ushell); + } + endusershell(); + + + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) + method = TEST_BUILD_SNAPSHOT; + else { + if (debug) + printf("can't access the snapshot file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } else { + rv = TEST_SNAPSHOT_FILE_READ(usershell, snapshot_file, + &td_snap, usershell_read_snapshot_func); + if (rv != 0) { + if (debug) + printf("error reading snapshot file\n"); + goto fin; + } + } + } + + switch (method) { + case TEST_GETUSERSHELL: + if (snapshot_file != NULL) { + rv = DO_2PASS_TEST(usershell, &td, &td_snap, + compare_usershell, NULL); + } + break; + case TEST_BUILD_SNAPSHOT: + if (snapshot_file != NULL) { + rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file, &td, + sdump_usershell); + } + break; + default: + rv = 0; + break; + }; + +fin: + TEST_DATA_DESTROY(usershell, &td_snap); + TEST_DATA_DESTROY(usershell, &td); + free(snapshot_file); + return (rv); + +} diff --git a/tools/regression/lib/libc/nss/test-getusershell.t b/tools/regression/lib/libc/nss/test-getusershell.t new file mode 100644 index 0000000..16a392a --- /dev/null +++ b/tools/regression/lib/libc/nss/test-getusershell.t @@ -0,0 +1,22 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..1 +do_test 1 'getusershell() snapshot' '-s snapshot_usershell' diff --git a/tools/regression/lib/libc/nss/testutil.h b/tools/regression/lib/libc/nss/testutil.h new file mode 100644 index 0000000..f1e91c2 --- /dev/null +++ b/tools/regression/lib/libc/nss/testutil.h @@ -0,0 +1,334 @@ +/*- + * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/queue.h> + +#define DECLARE_TEST_DATA(ent) \ +struct ent##_entry { \ + struct ent data; \ + STAILQ_ENTRY(ent##_entry) entries; \ +}; \ + \ +struct ent##_test_data { \ + void (*clone_func)(struct ent *, struct ent const *); \ + void (*free_func)(struct ent *); \ + \ + STAILQ_HEAD(ent_head, ent##_entry) snapshot_data; \ +}; \ + \ +void __##ent##_test_data_init(struct ent##_test_data *, \ + void (*)(struct ent *, struct ent const *), \ + void (*freef)(struct ent *)); \ +void __##ent##_test_data_destroy(struct ent##_test_data *); \ + \ +void __##ent##_test_data_append(struct ent##_test_data *, struct ent *data);\ +int __##ent##_test_data_foreach(struct ent##_test_data *, \ + int (*)(struct ent *, void *), void *); \ +int __##ent##_test_data_compare(struct ent##_test_data *, \ + struct ent##_test_data *, int (*)(struct ent *, struct ent *, \ + void *), void *); \ +struct ent *__##ent##_test_data_find(struct ent##_test_data *, struct ent *,\ + int (*)(struct ent *, struct ent *, void *), void *); \ +void __##ent##_test_data_clear(struct ent##_test_data *); + +#define TEST_DATA_INIT(ent, td, clonef, freef)\ + __##ent##_test_data_init(td, clonef, freef) +#define TEST_DATA_DESTROY(ent, td) __##ent##_test_data_destroy(td) +#define TEST_DATA_APPEND(ent, td, d) __##ent##_test_data_append(td, d) +#define TEST_DATA_FOREACH(ent, td, f, mdata)\ + __##ent##_test_data_foreach(td, f, mdata) +#define TEST_DATA_COMPARE(ent, td1, td2, fcmp, mdata)\ + __##ent##_test_data_compare(td1, td2, fcmp, mdata); +#define TEST_DATA_FIND(ent, td, d, fcmp, mdata)\ + __##ent##_test_data_find(td, d, fcmp, mdata) +#define TEST_DATA_CLEAR(ent, td) __##ent##_test_data_clear(td) + +#define IMPLEMENT_TEST_DATA(ent) \ +void \ +__##ent##_test_data_init(struct ent##_test_data *td, \ + void (*clonef)(struct ent *, struct ent const *), \ + void (*freef)(struct ent *)) \ +{ \ + assert(td != NULL); \ + assert(clonef != NULL); \ + assert(freef != NULL); \ + \ + memset(td, 0, sizeof(*td)); \ + td->clone_func = clonef; \ + td->free_func = freef; \ + STAILQ_INIT(&td->snapshot_data); \ +} \ + \ +void \ +__##ent##_test_data_destroy(struct ent##_test_data *td) \ +{ \ + __##ent##_test_data_clear(td); \ +} \ + \ +void \ +__##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\ +{ \ + struct ent##_entry *e; \ + \ + assert(td != NULL); \ + assert(app_data != NULL); \ + \ + e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry)); \ + assert(e != NULL); \ + memset(e, 0, sizeof(struct ent##_entry)); \ + \ + td->clone_func(&e->data, app_data); \ + STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries); \ +} \ + \ +int \ +__##ent##_test_data_foreach(struct ent##_test_data *td, \ + int (*forf)(struct ent *, void *), void *mdata) \ +{ \ + struct ent##_entry *e; \ + int rv; \ + \ + assert(td != NULL); \ + assert(forf != NULL); \ + \ + rv = 0; \ + STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ + rv = forf(&e->data, mdata); \ + if (rv != 0) \ + break; \ + } \ + \ + return (rv); \ +} \ + \ +int \ +__##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\ + int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\ +{ \ + struct ent##_entry *e1, *e2; \ + int rv; \ + \ + assert(td1 != NULL); \ + assert(td2 != NULL); \ + assert(cmp_func != NULL); \ + \ + e1 = STAILQ_FIRST(&td1->snapshot_data); \ + e2 = STAILQ_FIRST(&td2->snapshot_data); \ + \ + rv = 0; \ + do { \ + if ((e1 == NULL) || (e2 == NULL)) { \ + if (e1 == e2) \ + return (0); \ + else \ + return (-1); \ + } \ + \ + rv = cmp_func(&e1->data, &e2->data, mdata); \ + e1 = STAILQ_NEXT(e1, entries); \ + e2 = STAILQ_NEXT(e2, entries); \ + } while (rv == 0); \ + \ + return (rv); \ +} \ + \ +struct ent * \ +__##ent##_test_data_find(struct ent##_test_data *td, struct ent *data, \ + int (*cmp)(struct ent *, struct ent *, void *), void *mdata) \ +{ \ + struct ent##_entry *e; \ + struct ent *result; \ + \ + assert(td != NULL); \ + assert(cmp != NULL); \ + \ + result = NULL; \ + STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ + if (cmp(&e->data, data, mdata) == 0) { \ + result = &e->data; \ + break; \ + } \ + } \ + \ + return (result); \ +} \ + \ + \ +void \ +__##ent##_test_data_clear(struct ent##_test_data *td) \ +{ \ + struct ent##_entry *e; \ + assert(td != NULL); \ + \ + while (!STAILQ_EMPTY(&td->snapshot_data)) { \ + e = STAILQ_FIRST(&td->snapshot_data); \ + STAILQ_REMOVE_HEAD(&td->snapshot_data, entries); \ + \ + td->free_func(&e->data); \ + free(e); \ + } \ +} + + \ +#define DECLARE_TEST_FILE_SNAPSHOT(ent) \ +struct ent##_snp_param { \ + FILE *fp; \ + void (*sdump_func)(struct ent *, char *, size_t); \ +}; \ + \ +int __##ent##_snapshot_write_func(struct ent *, void *); \ +int __##ent##_snapshot_write(char const *, struct ent##_test_data *, \ + void (*)(struct ent *, char *, size_t)); \ +int __##ent##_snapshot_read(char const *, struct ent##_test_data *, \ + int (*)(struct ent *, char *)); + +#define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f) \ + __##ent##_snapshot_write(fname, td, f) +#define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f) \ + __##ent##_snapshot_read(fname, td, f) + +#define IMPLEMENT_TEST_FILE_SNAPSHOT(ent) \ +int \ +__##ent##_snapshot_write_func(struct ent *data, void *mdata) \ +{ \ + char buffer[1024]; \ + struct ent##_snp_param *param; \ + \ + assert(data != NULL); \ + \ + param = (struct ent##_snp_param *)mdata; \ + param->sdump_func(data, buffer, sizeof(buffer)); \ + fputs(buffer, param->fp); \ + fputc('\n', param->fp); \ + \ + return (0); \ +} \ + \ +int \ +__##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \ + void (*sdump_func)(struct ent *, char *, size_t)) \ +{ \ + struct ent##_snp_param param; \ + \ + assert(fname != NULL); \ + assert(td != NULL); \ + \ + param.fp = fopen(fname, "w"); \ + if (param.fp == NULL) \ + return (-1); \ + \ + param.sdump_func = sdump_func; \ + __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, ¶m);\ + fclose(param.fp); \ + \ + return (0); \ +} \ + \ +int \ +__##ent##_snapshot_read(char const *fname, struct ent##_test_data *td, \ + int (*read_func)(struct ent *, char *)) \ +{ \ + char buffer[1024]; \ + struct ent data; \ + char *s; \ + FILE *fi; \ + size_t len; \ + int rv; \ + \ + assert(fname != NULL); \ + assert(td != NULL); \ + \ + fi = fopen(fname, "r"); \ + if (fi == NULL) \ + return (-1); \ + \ + rv = 0; \ + memset(buffer, 0, sizeof(buffer)); \ + while (!feof(fi)) { \ + s = fgets(buffer, sizeof(buffer), fi); \ + if (s != NULL && s[0] != '#') { \ + len = strlen(s); \ + if (len == 0) \ + continue; \ + if (buffer[len - 1] == '\n') \ + buffer[len -1] = '\0'; \ + \ + rv = read_func(&data, s); \ + if (rv == 0) { \ + __##ent##_test_data_append(td, &data); \ + td->free_func(&data); \ + } else \ + goto fin; \ + } \ + } \ + \ +fin: \ + fclose(fi); \ + return (rv); \ +} + +#define DECLARE_1PASS_TEST(ent) \ +int __##ent##_1pass_test(struct ent##_test_data *, \ + int (*)(struct ent *, void *), \ + void *); + +#define DO_1PASS_TEST(ent, td, f, mdata) \ + __##ent##_1pass_test(td, f, mdata) + +#define IMPLEMENT_1PASS_TEST(ent) \ +int \ +__##ent##_1pass_test(struct ent##_test_data *td, \ + int (*tf)(struct ent *, void *), \ + void *mdata) \ +{ \ + int rv; \ + rv = __##ent##_test_data_foreach(td, tf, mdata); \ + \ + return (rv); \ +} + +#define DECLARE_2PASS_TEST(ent) \ +int __##ent##_2pass_test(struct ent##_test_data *, \ + struct ent##_test_data *, \ + int (*)(struct ent *, struct ent *, void *), void *); + +#define DO_2PASS_TEST(ent, td1, td2, f, mdata) \ + __##ent##_2pass_test(td1, td2, f, mdata) + +#define IMPLEMENT_2PASS_TEST(ent) \ +int \ +__##ent##_2pass_test(struct ent##_test_data *td1, \ + struct ent##_test_data *td2, \ + int (*cmp_func)(struct ent *, struct ent *, void *), \ + void *cmp_mdata) \ +{ \ + int rv; \ + \ + rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata); \ + return (rv); \ +} diff --git a/tools/regression/lib/libc/regex/Makefile b/tools/regression/lib/libc/regex/Makefile new file mode 100644 index 0000000..f91bef2 --- /dev/null +++ b/tools/regression/lib/libc/regex/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +GROT= ../../../../../lib/libc/regex/grot + +.PHONY: tests +tests: + cd ${GROT}; make && echo "PASS regex" + +.PHONY: clean +clean: + cd ${GROT}; make spotless diff --git a/tools/regression/lib/libc/resolv/Makefile b/tools/regression/lib/libc/resolv/Makefile new file mode 100644 index 0000000..9b4e6b1 --- /dev/null +++ b/tools/regression/lib/libc/resolv/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2004/05/13 19:17:12 christos Exp $ +# $FreeBSD$ + +PROG= resolv +NO_MAN= + +# Note: this test relies on being dynamically linked. You will get a +# spurious PASS for a statically linked test. +DPADD+= ${LIBPTHREAD} +LDADD+= -lpthread + +regress: ${PROG} + ./${PROG} -r ${.CURDIR}/mach + +.include <bsd.prog.mk> diff --git a/tools/regression/lib/libc/resolv/mach b/tools/regression/lib/libc/resolv/mach new file mode 100644 index 0000000..f3c3981 --- /dev/null +++ b/tools/regression/lib/libc/resolv/mach @@ -0,0 +1,92 @@ +above.warped.net +anoncvs.cirr.com +anoncvs.isc.netbsd.org +anoncvs.leo.org +anoncvs.netbsd.lt +anoncvs.netbsd.ro +anoncvs.netbsd.se +antioche.antioche.eu.org +boulder.tele.dk +centaurus.4web.cz +chur.math.ntnu.no +cnftp.bjpu.edu.cn +console.netbsd.org +cvs.fi.netbsd.org +cvs.mikrolahti.fi +cvs.netbsd.org +cvsup-netbsd.leo.org +cvsup.netbsd.se +cvsup.pasta.cs.uit.no +ftp.bitcon.no +ftp.chg.ru +ftp.duth.gr +ftp.estpak.ee +ftp.fsn.hu +ftp.funet.fi +ftp.grondar.za +ftp.leo.org +ftp.netbsd.lt +ftp.netbsd.org +ftp.nluug.nl +ftp.plig.org +ftp.uni-erlangen.de +ftp.xgate.co.kr +gd.tuwien.ac.at +gort.ludd.luth.se +grappa.unix-ag.uni-kl.de +info.wins.uva.nl +irc.warped.net +knug.youn.co.kr +lala.iri.co.jp +mail.jp.netbsd.org +mail.kr.netbsd.org +mail.netbsd.org +melanoma.cs.rmit.edu.au +mirror.aarnet.edu.au +mirror.netbsd.com.br +mirror03.inet.tele.dk +moon.vub.ac.be +nbwww.sergei.cc +net.bsd.cz +netbsd.3miasto.net +netbsd.4ka.mipt.ru +netbsd.apk.od.ua +netbsd.csie.nctu.edu.tw +netbsd.enderunix.org +netbsd.ftp.fu-berlin.de +netbsd.netlead.com.au +netbsd.nsysu.edu.tw +netbsd.pair.com +netbsd.stevens-tech.edu +netbsd.triada.bg +netbsd.unix.net.nz +netbsd.unixtech.be +netbsd.vejas.lt +netbsd.wagener-consulting.lu +netbsd.zarco.org +netbsdiso.interoute.net.uk +netbsdwww.bitcon.no +netbsdwww.cordef.com.pl +netbsdwww.cs.rmit.edu.au +netbsdwww.interoute.net.uk +news.gw.com +ns.netbsd.org +pigu.iri.co.jp +pluto.cdpa.nsysu.edu.tw +projects.slowass.net +server6.pasta.cs.uit.no +skeleton.phys.spbu.ru +snoopy.allbsd.org +spike.allbsd.org +sundry.netbsd.org +tanya.sergei.cc +web-a.fi.gw.com +web-a.us.gw.com +web.netbsd.mirror.arhea.net +www.en.netbsd.de +www.netbsd.cl +www.netbsd.nl +www.netbsd.org +www.netbsd.ro +zathras.netbsd.org +zeppo.rediris.es diff --git a/tools/regression/lib/libc/resolv/resolv.c b/tools/regression/lib/libc/resolv/resolv.c new file mode 100644 index 0000000..dc925d3 --- /dev/null +++ b/tools/regression/lib/libc/resolv/resolv.c @@ -0,0 +1,330 @@ +/* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* $FreeBSD$ */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $"); + +#include <sys/types.h> +#include <sys/socket.h> +#include <pthread.h> +#include <stdio.h> +#include <netdb.h> +#include <stdlib.h> +#include <unistd.h> +#include <err.h> +#include <string.h> +#include <stringlist.h> + +#define NTHREADS 10 +#define NHOSTS 100 +#define WS " \t\n\r" + +enum method { + METHOD_GETADDRINFO, + METHOD_GETHOSTBY, + METHOD_GETIPNODEBY +}; + +static StringList *hosts = NULL; +static int debug = 0; +static enum method method = METHOD_GETADDRINFO; +static int reverse = 0; +static int *ask = NULL; +static int *got = NULL; + +static void usage(void) __attribute__((__noreturn__)); +static void load(const char *); +static void resolvone(int); +static void *resolvloop(void *); +static void run(int *); + +static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; + +static void +usage(void) +{ + (void)fprintf(stderr, + "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n", + getprogname()); + exit(1); +} + +static void +load(const char *fname) +{ + FILE *fp; + size_t len; + char *line; + + if ((fp = fopen(fname, "r")) == NULL) + err(1, "Cannot open `%s'", fname); + while ((line = fgetln(fp, &len)) != NULL) { + char c = line[len]; + char *ptr; + line[len] = '\0'; + for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) + sl_add(hosts, strdup(ptr)); + line[len] = c; + } + + (void)fclose(fp); +} + +static int +resolv_getaddrinfo(pthread_t self, char *host, int port) +{ + char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; + struct addrinfo hints, *res; + int error, len; + + snprintf(portstr, sizeof(portstr), "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, portstr, &hints, &res); + if (debug) { + len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", + self, host, error ? "not found" : "ok"); + (void)write(STDOUT_FILENO, buf, len); + } + if (error == 0 && reverse) { + memset(hbuf, 0, sizeof(hbuf)); + memset(pbuf, 0, sizeof(pbuf)); + getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), + pbuf, sizeof(pbuf), 0); + if (debug) { + len = snprintf(buf, sizeof(buf), + "%p: reverse %s %s\n", self, hbuf, pbuf); + (void)write(STDOUT_FILENO, buf, len); + } + } + if (error == 0) + freeaddrinfo(res); + return error; +} + +static int +resolv_gethostby(pthread_t self, char *host) +{ + char buf[1024]; + struct hostent *hp, *hp2; + int len; + + hp = gethostbyname(host); + if (debug) { + len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", + self, host, (hp == NULL) ? "not found" : "ok"); + (void)write(STDOUT_FILENO, buf, len); + } + if (hp && reverse) { + memcpy(buf, hp->h_addr, hp->h_length); + hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype); + if (hp2 && debug) { + len = snprintf(buf, sizeof(buf), + "%p: reverse %s\n", self, hp2->h_name); + (void)write(STDOUT_FILENO, buf, len); + } + } + return hp ? 0 : -1; +} + +static int +resolv_getipnodeby(pthread_t self, char *host) +{ + char buf[1024]; + struct hostent *hp, *hp2; + int len, h_error; + + hp = getipnodebyname(host, AF_INET, 0, &h_error); + if (debug) { + len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", + self, host, (hp == NULL) ? "not found" : "ok"); + (void)write(STDOUT_FILENO, buf, len); + } + if (hp && reverse) { + memcpy(buf, hp->h_addr, hp->h_length); + hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype, + &h_error); + if (hp2 && debug) { + len = snprintf(buf, sizeof(buf), + "%p: reverse %s\n", self, hp2->h_name); + (void)write(STDOUT_FILENO, buf, len); + } + if (hp2) + freehostent(hp2); + } + if (hp) + freehostent(hp); + return hp ? 0 : -1; +} + +static void +resolvone(int n) +{ + char buf[1024]; + pthread_t self = pthread_self(); + size_t i = (random() & 0x0fffffff) % hosts->sl_cur; + char *host = hosts->sl_str[i]; + struct addrinfo hints, *res; + int error, len; + + if (debug) { + len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", + self, n, host, (int)i); + (void)write(STDOUT_FILENO, buf, len); + } + switch (method) { + case METHOD_GETADDRINFO: + error = resolv_getaddrinfo(self, host, i); + break; + case METHOD_GETHOSTBY: + error = resolv_gethostby(self, host); + break; + case METHOD_GETIPNODEBY: + error = resolv_getipnodeby(self, host); + break; + default: + break; + } + pthread_mutex_lock(&stats); + ask[i]++; + got[i] += error == 0; + pthread_mutex_unlock(&stats); +} + +static void * +resolvloop(void *p) +{ + int *nhosts = (int *)p; + if (*nhosts == 0) + return; + do + resolvone(*nhosts); + while (--(*nhosts)); + return NULL; +} + +static void +run(int *nhosts) +{ + pthread_t self = pthread_self(); + if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) + err(1, "pthread_create"); +} + +int +main(int argc, char *argv[]) +{ + int nthreads = NTHREADS; + int nhosts = NHOSTS; + int i, c, done, *nleft; + hosts = sl_init(); + + srandom(1234); + + while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1) + switch (c) { + case 'A': + method = METHOD_GETADDRINFO; + break; + case 'd': + debug++; + break; + case 'h': + nhosts = atoi(optarg); + break; + case 'H': + method = METHOD_GETHOSTBY; + break; + case 'I': + method = METHOD_GETIPNODEBY; + break; + case 'n': + nthreads = atoi(optarg); + break; + case 'r': + reverse++; + break; + default: + usage(); + } + + for (i = optind; i < argc; i++) + load(argv[i]); + + if (hosts->sl_cur == 0) + usage(); + + if ((nleft = malloc(nthreads * sizeof(int))) == NULL) + err(1, "malloc"); + if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) + err(1, "calloc"); + if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) + err(1, "calloc"); + + + for (i = 0; i < nthreads; i++) { + nleft[i] = nhosts; + run(&nleft[i]); + } + + for (done = 0; !done;) { + done = 1; + for (i = 0; i < nthreads; i++) { + if (nleft[i] != 0) { + done = 0; + break; + } + } + sleep(1); + } + c = 0; + for (i = 0; i < hosts->sl_cur; i++) { + if (ask[i] != got[i] && got[i] != 0) { + warnx("Error: host %s ask %d got %d\n", + hosts->sl_str[i], ask[i], got[i]); + c++; + } + } + free(nleft); + free(ask); + free(got); + sl_free(hosts, 1); + return c; +} diff --git a/tools/regression/lib/libc/resolv/resolv.t b/tools/regression/lib/libc/resolv/resolv.t new file mode 100644 index 0000000..278ba06 --- /dev/null +++ b/tools/regression/lib/libc/resolv/resolv.t @@ -0,0 +1,24 @@ +#!/bin/sh +# $FreeBSD$ + +do_test() { + number=$1 + comment=$2 + opt=$3 + if ./$executable $opt; then + echo "ok $number - $comment" + else + echo "not ok $number - $comment" + fi +} + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +echo 1..3 +do_test 1 'getaddrinfo()' '-r mach' +do_test 2 'gethostbyname()' '-rH mach' +do_test 3 'getipnodebyname()' '-rI mach' diff --git a/tools/regression/lib/libc/stdio/Makefile b/tools/regression/lib/libc/stdio/Makefile new file mode 100644 index 0000000..35131e2 --- /dev/null +++ b/tools/regression/lib/libc/stdio/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTS= test-perror test-printfloat test-scanfloat +CFLAGS+= -lm + +.PHONY: tests +tests: ${TESTS} + for p in ${TESTS}; do ${.OBJDIR}/$$p; done + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/stdio/test-perror.c b/tools/regression/lib/libc/stdio/test-perror.c new file mode 100644 index 0000000..992b734 --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-perror.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test program for perror() as specified by IEEE Std. 1003.1-2001 and + * ISO/IEC 9899:1999. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void cleanup(void); +static char tmpfil[PATH_MAX]; + +int +main(int argc, char *argv[]) +{ + char lbuf[512]; + int i; + char *s; + + printf("1..1\n"); + + strcpy(tmpfil, _PATH_TMP "perror.XXXXXXXX"); + if (mkstemp(tmpfil) < 0) + err(1, "mkstemp"); + atexit(cleanup); + /* Reopen stderr on a file descriptor other than 2. */ + fclose(stderr); + for (i = 0; i < 3; i++) + dup(0); + if (freopen(tmpfil, "r+", stderr) == NULL) + err(1, "%s", tmpfil); + + /* + * Test that perror() doesn't call strerror() (4.4BSD bug), + * the two ways of omitting a program name, and the formatting when + * a program name is specified. + */ + s = strerror(ENOENT); + assert(strcmp(s, "No such file or directory") == 0); + errno = EPERM; + perror(NULL); + perror(""); + perror("test-perror"); + assert(strcmp(s, "No such file or directory") == 0); + + /* + * Read it back to check... + */ + rewind(stderr); + s = fgets(lbuf, sizeof(lbuf), stderr); + assert(s != NULL); + assert(strcmp(s, "Operation not permitted\n") == 0); + s = fgets(lbuf, sizeof(lbuf), stderr); + assert(s != NULL); + assert(strcmp(s, "Operation not permitted\n") == 0); + s = fgets(lbuf, sizeof(lbuf), stderr); + assert(s != NULL); + assert(strcmp(s, "test-perror: Operation not permitted\n") == 0); + s = fgets(lbuf, sizeof(lbuf), stderr); + assert(s == NULL); + fclose(stderr); + + printf("ok 1 - perror()\n"); + + return (0); +} + +static void +cleanup(void) +{ + + unlink(tmpfil); +} diff --git a/tools/regression/lib/libc/stdio/test-perror.t b/tools/regression/lib/libc/stdio/test-perror.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-perror.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/stdio/test-printfloat.c b/tools/regression/lib/libc/stdio/test-printfloat.c new file mode 100644 index 0000000..5717a15 --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-printfloat.c @@ -0,0 +1,341 @@ +/*- + * Copyright (c) 2002, 2005 David Schultz <das@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test for printf() floating point formats. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <err.h> +#include <fenv.h> +#include <float.h> +#include <locale.h> +#include <math.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#define testfmt(result, fmt, ...) \ + _testfmt((result), __LINE__, #__VA_ARGS__, fmt, __VA_ARGS__) +void _testfmt(const char *, int, const char *, const char *, ...); +void smash_stack(void); + +int +main(int argc, char *argv[]) +{ + + printf("1..11\n"); + assert(setlocale(LC_NUMERIC, "")); + + /* + * Basic tests of decimal output functionality. + */ + testfmt(" 1.000000E+00", "%13E", 1.0); + testfmt(" 1.000000", "%13f", 1.0); + testfmt(" 1", "%13G", 1.0); + testfmt(" 1.000000E+00", "%13LE", 1.0L); + testfmt(" 1.000000", "%13Lf", 1.0L); + testfmt(" 1", "%13LG", 1.0L); + + testfmt("2.718282", "%.*f", -2, 2.7182818); + + testfmt("1.234568e+06", "%e", 1234567.8); + testfmt("1234567.800000", "%f", 1234567.8); + testfmt("1.23457E+06", "%G", 1234567.8); + testfmt("1.234568e+06", "%Le", 1234567.8L); + testfmt("1234567.800000", "%Lf", 1234567.8L); + testfmt("1.23457E+06", "%LG", 1234567.8L); + +#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) + testfmt("123456789.864210", "%Lf", 123456789.8642097531L); + testfmt("-1.23457E+08", "%LG", -123456789.8642097531L); + testfmt("123456789.8642097531", "%.10Lf", 123456789.8642097531L); + testfmt(" 3.141592653589793238e-4000", "%L27.18Le", + 3.14159265358979323846e-4000L); +#endif + + printf("ok 1 - printfloat\n"); + + /* + * Infinities and NaNs + */ + testfmt("nan", "%e", NAN); + testfmt("NAN", "%F", NAN); + testfmt("nan", "%g", NAN); + testfmt("NAN", "%LE", (long double)NAN); + testfmt(" nan", "%05e", NAN); + + testfmt("INF", "%E", HUGE_VAL); + testfmt("-inf", "%f", -HUGE_VAL); + testfmt("+inf", "%+g", HUGE_VAL); + testfmt(" inf", "%4.2Le", HUGE_VALL); + testfmt("-inf", "%Lf", -HUGE_VALL); + testfmt(" inf", "%05e", HUGE_VAL); + testfmt(" -inf", "%05e", -HUGE_VAL); + + printf("ok 2 - printfloat\n"); + + /* + * Padding + */ + testfmt("0.000000e+00", "%e", 0.0); + testfmt("0.000000", "%F", (double)0.0); + testfmt("0", "%G", 0.0); + testfmt(" 0", "%3.0Lg", 0.0L); + testfmt(" 0", "%5.0f", 0.001); + printf("ok 3 - printfloat\n"); + + /* + * Precision specifiers + */ + testfmt("1.0123e+00", "%.4e", 1.0123456789); + testfmt("1.0123", "%.4f", 1.0123456789); + testfmt("1.012", "%.4g", 1.0123456789); + testfmt("1.2346e-02", "%.4e", 0.0123456789); + testfmt("0.0123", "%.4f", 0.0123456789); + testfmt("0.01235", "%.4g", 0.0123456789); + printf("ok 4 - printfloat\n"); + + /* + * Thousands' separators and other locale fun + */ + testfmt("12345678.0625", "%'.04f", 12345678.0625); + testfmt("0012345678.0625", "%'015.4F", 12345678.0625); + + assert(setlocale(LC_NUMERIC, "hi_IN.ISCII-DEV")); /* grouping == 2;3 */ + testfmt("123,456,78.0625", "%'.4f", 12345678.0625); + testfmt("00123,456,78.0625", "%'017.4F", 12345678.0625); + testfmt(" 90,00", "%'6.0f", 9000.0); + testfmt("90,00.0", "%'.1f", 9000.0); + + assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ + testfmt("3,1415", "%g", 3.1415); + + /* thousands=. decimalpoint=, grouping=3;3 */ + assert(setlocale(LC_NUMERIC, "el_GR.ISO8859-7")); /* decimalpoint==, */ + testfmt("1.234,00", "%'.2f", 1234.00); + testfmt("123.456,789", "%'.3f", 123456.789); + + assert(setlocale(LC_NUMERIC, "")); + testfmt("12345678.062500", "%'f", 12345678.0625); + testfmt("9000.000000", "%'f", 9000.0); + + printf("ok 5 - printfloat\n"); + + /* + * Signed conversions + */ + testfmt("+2.500000e-01", "%+e", 0.25); + testfmt("+0.000000", "%+F", 0.0); + testfmt("-1", "%+g", -1.0); + + testfmt("-1.000000e+00", "% e", -1.0); + testfmt("+1.000000", "% +f", 1.0); + testfmt(" 1", "% g", 1.0); + testfmt(" 0", "% g", 0.0); + + printf("ok 6 - printfloat\n"); + + /* + * ``Alternate form'' + */ + testfmt("1.250e+00", "%#.3e", 1.25); + testfmt("123.000000", "%#f", 123.0); + testfmt(" 12345.", "%#7.5g", 12345.0); + testfmt(" 1.00000", "%#8g", 1.0); + testfmt("0.0", "%#.2g", 0.0); + printf("ok 7 - printfloat\n"); + + /* + * Padding and decimal point placement + */ + testfmt("03.2E+00", "%08.1E", 3.25); + testfmt("003.25", "%06.2F", 3.25); + testfmt("0003.25", "%07.4G", 3.25); + + testfmt("3.14159e-05", "%g", 3.14159e-5); + testfmt("0.000314159", "%g", 3.14159e-4); + testfmt("3.14159e+06", "%g", 3.14159e6); + testfmt("314159", "%g", 3.14159e5); + testfmt("314159.", "%#g", 3.14159e5); + + testfmt(" 9.000000e+03", "%13e", 9000.0); + testfmt(" 9000.000000", "%12f", 9000.0); + testfmt(" 9000", "%5g", 9000.0); + testfmt(" 900000.", "%#8g", 900000.0); + testfmt(" 9e+06", "%6g", 9000000.0); + testfmt(" 9.000000e-04", "%13e", 0.0009); + testfmt(" 0.000900", "%9f", 0.0009); + testfmt(" 0.0009", "%7g", 0.0009); + testfmt(" 9e-05", "%6g", 0.00009); + testfmt(" 9.00000e-05", "%#12g", 0.00009); + testfmt(" 9.e-05", "%#7.1g", 0.00009); + + testfmt(" 0.0", "%4.1f", 0.0); + testfmt("90.0", "%4.1f", 90.0); + testfmt(" 100", "%4.0f", 100.0); + testfmt("9.0e+01", "%4.1e", 90.0); + testfmt("1e+02", "%4.0e", 100.0); + + printf("ok 8 - printfloat\n"); + + /* + * Decimal rounding + */ + fesetround(FE_DOWNWARD); + testfmt("4.437", "%.3f", 4.4375); + testfmt("-4.438", "%.3f", -4.4375); + testfmt("4.437", "%.3Lf", 4.4375L); + testfmt("-4.438", "%.3Lf", -4.4375L); + + fesetround(FE_UPWARD); + testfmt("4.438", "%.3f", 4.4375); + testfmt("-4.437", "%.3f", -4.4375); + testfmt("4.438", "%.3Lf", 4.4375L); + testfmt("-4.437", "%.3Lf", -4.4375L); + + fesetround(FE_TOWARDZERO); + testfmt("4.437", "%.3f", 4.4375); + testfmt("-4.437", "%.3f", -4.4375); + testfmt("4.437", "%.3Lf", 4.4375L); + testfmt("-4.437", "%.3Lf", -4.4375L); + + fesetround(FE_TONEAREST); + testfmt("4.438", "%.3f", 4.4375); + testfmt("-4.438", "%.3f", -4.4375); + testfmt("4.438", "%.3Lf", 4.4375L); + testfmt("-4.438", "%.3Lf", -4.4375L); + + printf("ok 9 - printfloat\n"); + + /* + * Hexadecimal floating point (%a, %A) tests. Some of these + * are only valid if the implementation converts to hex digits + * on nibble boundaries. + */ + testfmt("0x0p+0", "%a", 0x0.0p0); + testfmt("0X0.P+0", "%#LA", 0x0.0p0L); + testfmt("inf", "%La", (long double)INFINITY); + testfmt("+INF", "%+A", INFINITY); + testfmt("nan", "%La", (long double)NAN); + testfmt("NAN", "%A", NAN); + + testfmt(" 0x1.23p+0", "%10a", 0x1.23p0); + testfmt(" 0x1.23p-500", "%12a", 0x1.23p-500); + testfmt(" 0x1.2p+40", "%10.1a", 0x1.23p40); + testfmt(" 0X1.230000000000000000000000P-4", "%32.24A", 0x1.23p-4); + testfmt("0x1p-1074", "%a", 0x1p-1074); + testfmt("0x1.2345p-1024", "%a", 0x1.2345p-1024); + +#if (LDBL_MANT_DIG == 64) && !defined(__i386__) + testfmt("0xc.90fdaa22168c234p-2", "%La", 0x3.243f6a8885a308dp0L); + testfmt("0x8p-16448", "%La", 0x1p-16445L); + testfmt("0x9.8765p-16384", "%La", 0x9.8765p-16384L); +#elif (LDBL_MANT_DIG == 113) + testfmt("0x1.921fb54442d18469898cc51701b8p+1", "%La", + 0x3.243f6a8885a308d313198a2e037p0L); + testfmt("0x1p-16494", "%La", 0x1p-16494L); + testfmt("0x1.2345p-16384", "%La", 0x1.2345p-16384L); +#else + testfmt("0xc.90fdaa22168cp-2", "%La", 0x3.243f6a8885a31p0L); + testfmt("0x8p-1077", "%La", 0x1p-1074L); + testfmt("0x9.8765p-1024", "%La", 0x9.8765p-1024L); +#endif + + printf("ok 10 - printfloat\n"); + + /* + * Hexadecimal rounding + */ + fesetround(FE_TOWARDZERO); + testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0); + + fesetround(FE_DOWNWARD); + testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23457p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0); + + fesetround(FE_UPWARD); + testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23457p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0); + + fesetround(FE_TONEAREST); + testfmt("0x1.23456789abcdep+4", "%a", 0x1.23456789abcdep4); + testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0); + testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0); + testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0); + testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0); + testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0); + testfmt("0x2.00p-1030", "%.2a", 0x1.fffp-1030); + testfmt("0x2.00p-1027", "%.2a", 0xf.fffp-1030); + testfmt("0x1.83p+0", "%.2a", 1.51); + + printf("ok 11 - printfloat\n"); + + return (0); +} + +void +smash_stack(void) +{ + static uint32_t junk = 0xdeadbeef; + uint32_t buf[512]; + int i; + + for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++) + buf[i] = junk; +} + +void +_testfmt(const char *result, int line, const char *argstr, const char *fmt,...) +{ + char s[100]; + va_list ap; + + va_start(ap, fmt); + smash_stack(); + vsnprintf(s, sizeof(s), fmt, ap); + if (strcmp(result, s) != 0) { + fprintf(stderr, + "%d: printf(\"%s\", %s) ==> [%s], expected [%s]\n", + line, fmt, argstr, s, result); + abort(); + } +} diff --git a/tools/regression/lib/libc/stdio/test-printfloat.t b/tools/regression/lib/libc/stdio/test-printfloat.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-printfloat.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/stdio/test-scanfloat.c b/tools/regression/lib/libc/stdio/test-scanfloat.c new file mode 100644 index 0000000..ef6faae --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-scanfloat.c @@ -0,0 +1,293 @@ +/*- + * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test for scanf() floating point formats. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <fenv.h> +#include <float.h> +#include <locale.h> +#include <math.h> +#include <stdio.h> +#include <string.h> + +#define eq(type, a, b) _eq(type##_EPSILON, (a), (b)) +static int _eq(long double epsilon, long double a, long double b); + +extern int __scanfdebug; + +int +main(int argc, char *argv[]) +{ + char buf[128]; + long double ld = 0.0; + double d = 0.0; + float f = 0.0; + + printf("1..3\n"); + + buf[0] = '\0'; + assert(setlocale(LC_NUMERIC, "")); + + __scanfdebug = 1; + + /* + * Various tests for normalized numbers + */ + sscanf("3.141592", "%e", &f); + assert(eq(FLT, f, 3.141592)); + + sscanf("3.141592653589793", "%lf", &d); + assert(eq(DBL, d, 3.141592653589793)); + + sscanf("1.234568e+06", "%E", &f); + assert(eq(FLT, f, 1.234568e+06)); + + sscanf("-1.234568e6", "%lF", &d); + assert(eq(DBL, d, -1.234568e6)); + + sscanf("+1.234568e-52", "%LG", &ld); + assert(eq(LDBL, ld, 1.234568e-52L)); + + sscanf("0.1", "%la", &d); + assert(eq(DBL, d, 0.1)); + + sscanf("00.2", "%lA", &d); + assert(eq(DBL, d, 0.2)); + + sscanf("123456", "%5le%s", &d, buf); + assert(eq(DBL, d, 12345.)); + assert(strcmp(buf, "6") == 0); + + sscanf("1.0Q", "%*5le%s", buf); + assert(strcmp(buf, "Q") == 0); + + sscanf("-1.23e", "%e%s", &f, buf); + assert(eq(FLT, f, -1.23)); + assert(strcmp(buf, "e") == 0); + + sscanf("1.25e+", "%le%s", &d, buf); + assert(eq(DBL, d, 1.25)); + assert(strcmp(buf, "e+") == 0); + + sscanf("1.23E4E5", "%le%s", &d, buf); + assert(eq(DBL, d, 1.23e4)); + assert(strcmp(buf, "E5") == 0); + + sscanf("12e6", "%le", &d); + assert(eq(DBL, d, 12e6)); + + sscanf("1.a", "%le%s", &d, buf); + assert(eq(DBL, d, 1.0)); + assert(strcmp(buf, "a") == 0); + + sscanf(".0p4", "%le%s", &d, buf); + assert(eq(DBL, d, 0.0)); + assert(strcmp(buf, "p4") == 0); + + d = 0.25; + assert(sscanf(".", "%le", &d) == 0); + assert(d == 0.25); + + sscanf("0x08", "%le", &d); + assert(d == 0x8p0); + + sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf); + assert(d == 0x90a.bcdefp+09); + assert(strcmp(buf, "a") == 0); + +#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) + sscanf("3.14159265358979323846", "%Lg", &ld); + assert(eq(LDBL, ld, 3.14159265358979323846L)); + + sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf); + assert(ld == 0x0.0123456789abcdefffp-3L); + assert(strcmp(buf, "g") == 0); +#endif + + sscanf("0xg", "%le%s", &d, buf); + assert(d == 0.0); + assert(strcmp(buf, "xg") == 0); + + assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ + + sscanf("1.23", "%le%s", &d, buf); + assert(d == 1.0); + assert(strcmp(buf, ".23") == 0); + + sscanf("1,23", "%le", &d); + assert(d == 1.23); + + assert(setlocale(LC_NUMERIC, "")); + + printf("ok 1 - scanfloat\n"); + + /* + * Infinity and NaN tests + */ + sscanf("-Inf", "%le", &d); + assert(d < 0.0 && isinf(d)); + + sscanf("iNfInItY and beyond", "%le%s", &d, buf); + assert(d > 0.0 && isinf(d)); + assert(strcmp(buf, " and beyond")); + + sscanf("NaN", "%le", &d); + assert(isnan(d)); + + sscanf("NAN(123Y", "%le%s", &d, buf); + assert(isnan(d)); + assert(strcmp(buf, "(123Y") == 0); + + sscanf("nan(f00f)plugh", "%le%s", &d, buf); + assert(isnan(d)); + assert(strcmp(buf, "plugh") == 0); + + sscanf("-nan", "%le", &d); + assert(isnan(d)); + + /* Only quiet NaNs should be returned. */ + sscanf("NaN", "%e", &f); + sscanf("nan", "%le", &d); + sscanf("nan", "%Le", &ld); + feclearexcept(FE_ALL_EXCEPT); + assert(f != f); + assert(d != d); + assert(ld != ld); + assert(fetestexcept(FE_INVALID) == 0); + sscanf("nan(1234)", "%e", &f); + sscanf("nan(1234)", "%le", &d); + sscanf("nan(1234)", "%Le", &ld); + feclearexcept(FE_ALL_EXCEPT); + assert(f != f); + assert(d != d); + assert(ld != ld); +#if 0 + /* + * POSIX says we should only generate quiet NaNs, but the gdtoa + * author convincingly argues that if you ask for a NaN format + * based on some implementation-defined string, you should get + * what you asked for, even if it's a signaling NaN. + */ + assert(fetestexcept(FE_INVALID) == 0); +#endif + + printf("ok 2 - scanfloat\n"); + + /* + * Rounding tests + */ + + fesetround(FE_DOWNWARD); + + sscanf("1.999999999999999999999999999999999", "%le", &d); + assert(d < 2.0); + sscanf("0x1.ffffffffffffffp0", "%le", &d); + assert(d < 2.0); + sscanf("1.999999999999999999999999999999999", "%Le", &ld); + assert(ld < 2.0); + + sscanf("1.0571892669084007", "%le", &d); + assert(d == 0x1.0ea3f4af0dc59p0); + sscanf("-1.0571892669084007", "%le", &d); + assert(d == -0x1.0ea3f4af0dc5ap0); + sscanf("1.0571892669084010", "%le", &d); + assert(d == 0x1.0ea3f4af0dc5ap0); + + sscanf("0x1.23p-5000", "%le", &d); + assert(d == 0.0); + + sscanf("0x1.2345678p-1050", "%le", &d); + assert(d == 0x1.234567p-1050); + + fesetround(FE_UPWARD); + + sscanf("1.0571892669084007", "%le", &d); + assert(d == 0x1.0ea3f4af0dc5ap0); + sscanf("-1.0571892669084007", "%le", &d); + assert(d == -0x1.0ea3f4af0dc59p0); + sscanf("1.0571892669084010", "%le", &d); + assert(d == 0x1.0ea3f4af0dc5bp0); + + sscanf("0x1.23p-5000", "%le", &d); + assert(d == 0x1p-1074); + + sscanf("0x1.2345678p-1050", "%le", &d); + assert(d == 0x1.234568p-1050); + + fesetround(FE_TOWARDZERO); + + sscanf("1.0571892669084007", "%le", &d); + assert(d == 0x1.0ea3f4af0dc59p0); + sscanf("-1.0571892669084007", "%le", &d); + assert(d == -0x1.0ea3f4af0dc59p0); + sscanf("1.0571892669084010", "%le", &d); + assert(d == 0x1.0ea3f4af0dc5ap0); + + sscanf("0x1.23p-5000", "%le", &d); + assert(d == 0.0); + + sscanf("0x1.2345678p-1050", "%le", &d); + assert(d == 0x1.234567p-1050); + + fesetround(FE_TONEAREST); + + /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */ + sscanf("1.0571892669084007", "%le", &d); + assert(d == 0x1.0ea3f4af0dc59p0); + sscanf("-1.0571892669084007", "%le", &d); + assert(d == -0x1.0ea3f4af0dc59p0); + sscanf("1.0571892669084010", "%le", &d); + assert(d == 0x1.0ea3f4af0dc5bp0); + + /* strtod() should round small numbers to 0. */ + sscanf("0x1.23p-5000", "%le", &d); + assert(d == 0.0); + + /* Extra digits in a denormal shouldn't break anything. */ + sscanf("0x1.2345678p-1050", "%le", &d); + assert(d == 0x1.234568p-1050); + + printf("ok 3 - scanfloat\n"); + + return (0); +} + +static int +_eq(long double epsilon, long double a, long double b) +{ + long double delta; + + delta = a - b; + if (delta < 0) /* XXX no fabsl() */ + delta = -delta; + return (delta <= epsilon); +} diff --git a/tools/regression/lib/libc/stdio/test-scanfloat.t b/tools/regression/lib/libc/stdio/test-scanfloat.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-scanfloat.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/stdlib/Makefile b/tools/regression/lib/libc/stdlib/Makefile new file mode 100644 index 0000000..c707795 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +TESTS= test-qsort \ + test-heapsort \ + test-mergesort + +.PHONY: tests +tests: ${TESTS} + for p in ${TESTS}; do ${.OBJDIR}/$$p; done + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/stdlib/test-heapsort.c b/tools/regression/lib/libc/stdlib/test-heapsort.c new file mode 100644 index 0000000..6ce8924 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-heapsort.c @@ -0,0 +1,66 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test for heapsort() routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +int +main(int argc, char *argv[]) +{ + int i, j; + int testvector[IVEC_LEN]; + int sresvector[IVEC_LEN]; + + printf("1..1\n"); + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using heapsort(3) */ + heapsort(testvector, j, sizeof(testvector[0]), sorthelp); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + assert(testvector[i] == sresvector[i]); + } + + printf("ok 1 - heapsort\n"); + + return(0); +} diff --git a/tools/regression/lib/libc/stdlib/test-heapsort.t b/tools/regression/lib/libc/stdlib/test-heapsort.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-heapsort.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/stdlib/test-mergesort.c b/tools/regression/lib/libc/stdlib/test-mergesort.c new file mode 100644 index 0000000..729d481 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-mergesort.c @@ -0,0 +1,66 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test for mergesort() routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +int +main(int argc, char *argv[]) +{ + int i, j; + int testvector[IVEC_LEN]; + int sresvector[IVEC_LEN]; + + printf("1..1\n"); + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using mergesort(3) */ + mergesort(testvector, j, sizeof(testvector[0]), sorthelp); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + assert(testvector[i] == sresvector[i]); + } + + printf("ok 1 - mergesort\n"); + + return(0); +} diff --git a/tools/regression/lib/libc/stdlib/test-mergesort.t b/tools/regression/lib/libc/stdlib/test-mergesort.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-mergesort.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/stdlib/test-qsort.c b/tools/regression/lib/libc/stdlib/test-qsort.c new file mode 100644 index 0000000..8a508e8 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-qsort.c @@ -0,0 +1,66 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test for qsort() routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +int +main(int argc, char *argv[]) +{ + int i, j; + int testvector[IVEC_LEN]; + int sresvector[IVEC_LEN]; + + printf("1..1\n"); + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using qsort(3) */ + qsort(testvector, j, sizeof(testvector[0]), sorthelp); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + assert(testvector[i] == sresvector[i]); + } + + printf("ok 1 - qsort\n"); + + return(0); +} diff --git a/tools/regression/lib/libc/stdlib/test-qsort.t b/tools/regression/lib/libc/stdlib/test-qsort.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-qsort.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/lib/libc/stdlib/test-sort.h b/tools/regression/lib/libc/stdlib/test-sort.h new file mode 100644 index 0000000..e060f72 --- /dev/null +++ b/tools/regression/lib/libc/stdlib/test-sort.h @@ -0,0 +1,269 @@ +/*- + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TEST_SORT_H +#define _TEST_SORT_H + +static int +sorthelp(const void *a, const void *b) +{ + const int *oa, *ob; + + oa = a; + ob = b; + /* Don't use "return *oa - *ob" since it's easy to cause overflow! */ + if (*oa > *ob) + return 1; + if (*oa < *ob) + return -1; + return 0; +} + +/* Reference sorting routine (slooow!) */ +static void +ssort(int v[], int nmemb) +{ + int i, j, k; + + for (i = 0; i < nmemb; i++) { + for (j = i + 1; j < nmemb; j++) { + if (v[j] < v[i]) { + k = v[i]; + v[i] = v[j]; + v[j] = k; + } + } + } +} + +/* Some random data */ +static int initvector[1024] = { + 599853225, 371951333, -428880425, 1450668530, 85530178, -460170550, + -270680269, 717137591, 106244401, -1138072905, -113532586, + 599690958, 464993720, 107690177, 24249019, -1151018550, 794225588, + 1494905642, -62951716, -734531757, 1197251494, 1020063925, + -634536734, -216634704, 617366508, -18840190, 481010395, + -1555785724, 128221950, -1747743676, 1119012320, -252160437, + 617137855, 1159833073, -106647920, -1570719046, -769400990, + -130308848, 1186546396, 215253591, 445832488, 160263176, 777264170, + -274636650, -696134447, 1057957088, -626175254, 188632134, + -98941793, -1602334908, -373717125, 885013862, 571258221, + -399572192, 407761463, -733249776, 12094800, -367046815, 178974501, + -452638559, -516580143, -94282073, 1411115180, -1151792797, + 1442815268, 1106583674, 515269284, -74019972, 598818901, 696848474, + -657910766, -287309335, 1538095746, 143543003, 851444033, + -947573348, 296222973, 1339592140, -947505360, 872027891, + -418844714, -583075597, -324758197, -964531573, 1016795914, + -866842580, -304084402, -286930819, 338975583, 803597943, + -452483372, 1525283506, -1185830826, -596405894, 905191340, + -1638026278, 106749913, 582771197, -730713796, 56052422, + 1498040174, 644967266, 182541575, 280483468, -1932835017, + -435546874, 940106007, 1753388509, -340355019, -231577358, + -714879035, 1051182949, 204261785, 1321346243, -895289878, + -240369893, 566608506, -350777580, -1384849829, -876816409, + 1013787299, -1408035937, -222626650, 1708168486, -645148461, + 1854654, -393012507, 179327030, -1607975548, -715202732, 730588290, + 246968517, -550975254, -101136772, -174103176, 1188941016, + 2004650834, -1501389866, -2021225998, 1219042515, -464113898, + 268565342, 126451123, -1045877126, -198918003, 310177444, + 1578314812, 1828867082, 453336898, -908485523, 749777130, + -1028565802, 61360571, 241484853, -175693399, 1816211059, + 533940889, -1496933703, 385185125, -821132413, -8923391, + -1429546239, 46190992, 449247332, -20432494, 778761611, -178782699, + -811194695, -632276211, 70196094, 890817525, -1447776908, + -323783741, -62333222, 954929503, 247668507, -1394420605, + 367913886, 1364926759, 1298781924, 357923028, -73644747, + -319744305, 61718202, -1454549286, 387493522, 2018321449, + 861026653, 289973298, 1755939093, -84772204, 43425266, -1325753781, + -679938775, 1228500370, -763816405, 548903035, 1765563727, + 425183052, 1424621863, -188287424, 554385654, 751831998, + 1377088085, 66622090, 139224450, -1305816167, 650140724, 593988868, + -444913321, 589045097, 1261428989, 101292769, -780376786, + 559307348, 1644593236, -1838606833, 53570301, -680576100, + -44969538, 268718267, -632104125, 276904628, 626299449, -11761453, + 545899086, -1027343598, -432251872, 539353494, -399575006, + -568383580, -677802882, 1296513472, 801202048, 806425805, 1983363, + 850487421, 38046173, 1535399484, 1998285544, -1301751898, + -46561973, 56545408, -1107662676, 456041145, -452923904, + -262219453, -371849200, 392524281, 1650231392, 1185585356, + 126610511, -1125389657, 1015981177, -1318481342, -213835789, + 1263484054, -654361441, 1408272041, -231555284, -1121778152, + -395512897, 332277674, -349703586, 1809474399, -223731607, + -1342224737, 736165236, 67535587, 89879082, 471445838, 423788300, + -384354470, 907475706, 154886390, -1406736539, -8558766, + -203405718, -422127884, 1048520863, 747418501, 87438975, 727668160, + -914936981, 428266976, -455742009, -949014605, 487159058, + -262526850, -309451504, -76928461, 1072951428, -1370953830, + 238231681, -1831047244, -405735199, -35941848, 469048670, + 505307987, -660553590, 876537439, -314195871, 999234339, + -1405846240, -579885695, 629067031, 863481510, -742301385, + -1723403128, -153070386, 782682839, -343111818, -877101810, + 1438467302, -319951459, -1585702508, -338381888, 484108815, + -1726935191, -749923706, 1657932127, -816151395, -566321865, + -133542331, 84961164, 598275578, 1302065347, -533098653, + -1766383037, 53169714, -464201288, 617735133, 862536123, + -141730724, -1967377125, -1023736305, -1012511106, 64484992, + -1250856831, 426409332, -355670055, -298251663, -867634978, + -776124819, 74018333, -425385214, -108004251, -1192766130, + 1294193867, -109867195, -78667637, 1164855393, -826007552, + -522528066, 1160283046, -1095276403, -1218917472, -396475366, + -77394733, -425603169, 251928357, -393559355, 1488845184, + 898455978, -773338691, -37627855, -345014717, 204298578, 209084274, + 1047080643, -414348222, 26496664, 705759824, 575149152, 604904761, + 624988690, 1446041250, 1000757225, -1354896151, 1422958189, + -1607165311, -832757521, 365074225, 1171764999, 1200795217, + -203957828, 23166236, -846818698, -547439867, -790192498, + -122123561, 914298013, 66225525, -36163174, -480698856, + -1269421818, 624641703, 254923102, 1564329013, -583609221, + -649433551, -743396069, 1182455435, 102658744, 285599336, + 692480463, -852737563, -660090184, 1374350065, 72300985, 690541659, + -1194212957, -1151816525, 157415641, 487398246, 1030153072, + 933723020, 1359181027, -1303457764, -1543773272, 774306017, + -854382652, 755485667, -864943584, -63242545, -1271480354, + 157720215, -205001173, 889984130, -581583822, -473779111, + -932136577, 735326252, 428638717, 1888884222, 561493709, + -1966427364, -1710208603, 340121869, 918894036, 927172509, + 904178436, 1476687667, 90796414, 651591731, -550913123, -42218158, + 637756529, 1091478400, 124976584, -48739309, -798898083, 393581349, + -1078624722, -789291577, 1010582542, -512317005, 1222773656, + 466454593, 1183558811, 822782663, -851624703, -850404012, + 1473672600, 852527073, 1073953362, 137635828, 936104739, -86567759, + -882563252, 1845232980, -737978404, -104703380, 149802989, + -349118325, 1479797538, 1966007488, 1254228842, 414304661, + -790805785, 31583329, -76864151, 558202855, -1447047313, 716720607, + -404224238, -54107627, 1747385914, -657407390, 202940208, + 1083067056, -532861378, 163426933, -130289277, 1301785258, + -302920320, -637947485, -644895903, -1668027530, 391890467, + -126586485, -536836984, -1154536413, -339505118, -1187229462, + -670985870, -601310813, -1350055158, -482479784, 139847714, + -253955849, 5190414, -542857077, 1175835684, -584165057, + 1132775766, -592091269, -891445655, -340995936, 736395810, + 779967964, 515095845, -1138437307, -259226729, -167820100, + -801611617, -282451622, -1313679283, -1436126694, 1258773990, + -717601098, -583559645, -1307478759, 1238647247, 1589011223, + -1029216445, -107030650, 400152690, -1349079913, 1428582247, + 21546946, 208807686, -169450574, -1086213374, -1242715198, + 669098277, 416626722, -1122525014, -1389466669, -391843085, + -56318357, 421040094, 212303518, 738666684, -1185364904, + -506192760, 646735912, -1424722633, 745226976, 1019191717, + -190891744, -310320868, -373655022, -665117060, 830760000, + 583906512, -330536027, 611092636, -321344259, -1255008904, + -777959046, -523043472, 88896910, 346062204, -163734816, 336635665, + 906060268, -128891583, 740952564, 916767203, 296514859, 198670559, + 358136672, -152253676, 12038867, -1469916749, -1020980597, + -897143313, 354240970, -97959800, 814172811, 1983363241, 264990663, + 105154676, 1060463014, 430172143, 375111946, -824526943, + -708877751, -1377442616, -236559551, 684724584, 1602131358, + -42140186, -763499840, -605167, 98575879, -376577598, 1689746083, + -777973879, -1396984691, -187780326, 281040966, 1858859521, + 158395760, 1022807978, -218458812, 811779708, 1495113833, + 1192561226, 629539535, -1365196683, -1120253162, 1091681956, + 134286445, 1172218369, -34093658, -137087343, -27869226, + -180889478, 55705436, 52362743, -1745516232, -926564477, + -513701675, -1666272054, 1457952810, 843953275, -478275722, + -1240291080, 101859661, -1606687523, 916365333, 314713310, + -22002688, 1019022641, -1171741314, -129050627, -211955813, + -1020176299, 1357865293, -609819628, 724533854, -1141449545, + 22285231, -97731145, -302329687, 191910894, -1300709885, + -644951895, 640448036, -1289009824, 1445456129, 846416471, + 1821291740, -1639640821, -712724532, -447475807, 132156847, + 258067455, 324301319, 278586969, -1544082357, 636007277, 977122066, + 127462480, 365126129, 1086276825, -432124148, 896598926, + -388550179, 273357331, -845018695, -1089465389, 384439820, + -558419772, 1476422025, 730712769, 190665059, -764968927, + -789708218, 637873581, 348429858, 1386000168, -638123594, + -842010345, -607926448, 19535163, -742771490, -18323344, 246155488, + 350409468, 1290907730, -492566468, 300358636, 501876267, 252441807, + 1233551975, -1431067042, 517177374, -1540299707, -948380761, + 1253997663, 693795998, 148707823, 152894502, 98729538, -30042824, + -563057441, 723726409, 367338961, 1395435261, 217868876, + 1220652431, 953572083, -1134905155, -734486813, -587470130, + -864647866, 1030737023, 781798521, -321076732, -460548153, + 122681678, -873728847, -1286304399, -75472885, 113390881, + -1556849198, -1070802176, 924389470, 957478910, 5974049, 709413506, + 476334647, 572869787, 776298405, -8822420, -99326499, -707855342, + -1187216303, 668038414, 262454769, -1120293198, -32011040, + 249812104, -101835410, 1082281087, -570183855, -954535179, + 1384361473, -983199686, 2017611313, 328926483, -878162849, + -1202254181, -225604951, 966898955, 247213529, -1257544612, + -197005970, -1039902730, -1947925142, 1752780907, -313410699, + -464474556, 416580338, -1063356643, -292212702, 57509168, + 1034124629, 1059212593, 468522867, 845369497, 1872717306, + -1216544764, -1419907623, 1376869956, -66585488, -1590974467, + -367070705, -1456529060, 791844031, 336217635, -1106832215, + 1476739427, -751018210, -1411671555, -1880387375, -1714242595, + 1169006474, -479442380, -892267555, -1471250266, -267888858, + 808634418, 1324777189, -585449929, 1127186951, 468768901, + -2002989138, -52352849, 186493053, 1258464606, 117157186, + 445919258, 908401949, -1112221136, 863904453, -942718649, + 796754809, -38943966, -781978872, -56814078, 1273857459, + -1781920832, 209979504, 811828269, -1150814437, 850061883, + -532968763, 252506408, -885025629, 391567580, -1295702482, + 574894420, 1462248349, 1622584325, -88443443, -1122006092, + -169758578, 456282338, -443233309, 436693483, -956563815, + -480221349, 435252860, -1114099391, 1060053979, -470893945, + -1273682879, -734596176, 639950927, -1278648701, 306274747, + -410562146, 1137869228, -1970746553, 1313830798, 1248071822, + -247297704, 1015218053, -1607348116, -261817613, -821413148, + -782942639, -628711083, 240953091, -629550668, -1584736319, + 856616893, -186759752, 197905373, 541638393, 603407919, -278480495, + 410077039, 544065371, -1509627427, 402918436, -450463799, + -131169308, 249920630, 1079548609, -927911828, 1444577689, + -353002528, -224292462, 1247795279, -790844631, -40427503, + 59829765, -332587567, 1319862109, -1261340753, 121711726, + 1342756342, -643495787, 100326201, -934436714, -69134888, + -898880561, -379524737, -577234570, -805827092, -1575493557, + -289920678, -476605057, 1235714994, -317239591, 418553949, + 410053338, -204985448, 1206503615, 202610372, -932244873, + 782207875, -288661931, -806814809, 1270953679, 2060991595, + -311412846, 327279979, 1148562672, 55239149, -610114433, + -1511688434, 87619740, -433503545, 326150519, -581293393, + -97417688, -289736140, -1543886029, -1251976119, 1585774446, + 1570011421, 432602745, 486343696, -834680922, 265004849, + -1132107706, 502627197, -815873818, 249635389, 1985714127, + -1095817653, -130743522, -645266828, -334621094, 199921747, + 1059256177, 378031303, 1519740920, 925540689, 1405957844, + 1387748290, -56138046, -770637828, -187984510, -1361735163, + 1294823206, -608941238, 451860688, -510549867, 1143516283, + -779090703, 1459305047, -600335915, -1684168049, 1516622316, + -631733335, -4360068, 499778796, 587600402, -1296000335, -37959743, + -1084203927, 1162902556, 246374600, -515103645, 341724568, + -702303954, 452229900, 485108287, 1170048553, -1510148355, + 611133912, 1997927484, -142022671, -724776653, -336090522, + 708283514, -1409637378, -2052637687, 376055110, 226628105, + -1714452033, -1776158002, 369167930, 1800807012, 710680889, + -69951947, -1223849766, -1862239787, 218536127, -656411794, + -1202269188, 609634805, -224425858, 519797951, 284223080, + 869408930, 270750206, -544967439, 2097168510, 31650971, -600985417, + -165303097, -257809088, -1043223971, 1827891621, -156827355, + 499719603 +}; + +#define IVEC_LEN (sizeof(initvector) / sizeof(initvector[0])) + +#endif diff --git a/tools/regression/lib/libc/string/Makefile b/tools/regression/lib/libc/string/Makefile new file mode 100644 index 0000000..af76f9d --- /dev/null +++ b/tools/regression/lib/libc/string/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +CFLAGS+= -I/usr/local/include +LDFLAGS+= -L/usr/local/lib +LDLIBS= -ltap + +TESTS= test-strerror + +.PHONY: tests +tests: ${TESTS} + for p in ${TESTS}; do ${.OBJDIR}/$$p; done + +.PHONY: clean +clean: + -rm -f ${TESTS} diff --git a/tools/regression/lib/libc/string/test-strerror.c b/tools/regression/lib/libc/string/test-strerror.c new file mode 100644 index 0000000..f5274ed --- /dev/null +++ b/tools/regression/lib/libc/string/test-strerror.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2001 Wes Peters <wes@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <tap.h> + +int +main(void) +{ + char buf[64]; + char *sret; + int iret; + + plan_tests(25); + + /* + * strerror() failure tests. + */ + errno = 0; + sret = strerror(0); + ok1(strcmp(sret, "Unknown error: 0") == 0); + ok1(errno == EINVAL); + + errno = 0; + sret = strerror(INT_MAX); + snprintf(buf, sizeof(buf), "Unknown error: %d", INT_MAX); + ok1(strcmp(sret, buf) == 0); + ok1(errno == EINVAL); + + /* + * strerror() success tests. + */ + errno = 0; + sret = strerror(EPERM); + ok1(strcmp(sret, "Operation not permitted") == 0); + ok1(errno == 0); + + errno = 0; + sret = strerror(EPFNOSUPPORT); + ok1(strcmp(sret, "Protocol family not supported") == 0); + ok1(errno == 0); + + errno = 0; + sret = strerror(ELAST); + ok1(errno == 0); + + /* + * strerror_r() failure tests. + */ + memset(buf, '*', sizeof(buf)); + iret = strerror_r(0, buf, sizeof(buf)); + ok1(strcmp(buf, "Unknown error: 0") == 0); + ok1(iret == EINVAL); + + memset(buf, '*', sizeof(buf)); + /* One byte too short. */ + iret = strerror_r(EPERM, buf, strlen("Operation not permitted")); + ok1(strcmp(buf, "Operation not permitte") == 0); + ok1(iret == ERANGE); + + memset(buf, '*', sizeof(buf)); + /* One byte too short. */ + iret = strerror_r(-1, buf, strlen("Unknown error: -1")); + ok1(strcmp(buf, "Unknown error: -") == 0); + ok1(iret == EINVAL); + + memset(buf, '*', sizeof(buf)); + /* Two bytes too short. */ + iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 1); + ok1(strcmp(buf, "Unknown error: ") == 0); + ok1(iret == EINVAL); + + memset(buf, '*', sizeof(buf)); + /* Three bytes too short. */ + iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 2); + ok1(strcmp(buf, "Unknown error:") == 0); + ok1(iret == EINVAL); + + memset(buf, '*', sizeof(buf)); + /* One byte too short. */ + iret = strerror_r(12345, buf, strlen("Unknown error: 12345")); + ok1(strcmp(buf, "Unknown error: 1234") == 0); + ok1(iret == EINVAL); + + /* + * strerror_r() success tests. + */ + memset(buf, '*', sizeof(buf)); + iret = strerror_r(EDEADLK, buf, sizeof(buf)); + ok1(strcmp(buf, "Resource deadlock avoided") == 0); + ok1(iret == 0); + + memset(buf, '*', sizeof(buf)); + iret = strerror_r(EPROCLIM, buf, sizeof(buf)); + ok1(strcmp(buf, "Too many processes") == 0); + ok1(iret == 0); + + return exit_status(); +} diff --git a/tools/regression/lib/libc/string/test-strerror.t b/tools/regression/lib/libc/string/test-strerror.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/lib/libc/string/test-strerror.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable |