diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index 90f65736c508..476b5b7d859e 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -2,8 +2,15 @@ .include -ATF_TESTS_C= arc4random_test +ATF_TESTS_C+= arc4random_test +ATF_TESTS_C+= fmtcheck2_test +ATF_TESTS_C+= fmtmsg_test +ATF_TESTS_C+= fnmatch2_test ATF_TESTS_C+= fpclassify2_test +ATF_TESTS_C+= ftw_test +ATF_TESTS_C+= popen_test +ATF_TESTS_C+= posix_spawn_test +ATF_TESTS_C+= wordexp_test # TODO: t_closefrom, t_cpuset, t_fmtcheck, t_randomid, t_sleep # TODO: t_siginfo (fixes require further inspection) @@ -53,7 +60,25 @@ DPADD.nice_test+= ${LIBPTHREAD} LDADD.syslog_test+= -lpthread DPADD.syslog_test+= ${LIBPTHREAD} +CFLAGS+= -I${.CURDIR} + +SRCS.fmtcheck2_test= fmtcheck_test.c +SRCS.fnmatch2_test= fnmatch_test.c + TESTS_SUBDIRS= execve TESTS_SUBDIRS+= posix_spawn +# The old testcase name +TEST_FNMATCH= test-fnmatch +CLEANFILES+= ${GEN_SH_CASE_TESTCASES} +sh-tests: .PHONY +.for target in clean obj depend all + @cd ${.CURDIR} && ${MAKE} PROG=${TEST_FNMATCH} \ + -DNO_SUBDIR ${target} +.endfor + @cd ${.OBJDIR} && ./${TEST_FNMATCH} -s 1 > \ + ${SRCTOP}/bin/sh/tests/builtins/case2.0 + @cd ${.OBJDIR} && ./${TEST_FNMATCH} -s 2 > \ + ${SRCTOP}/bin/sh/tests/builtins/case3.0 + .include diff --git a/tools/regression/lib/libc/gen/test-fmtcheck.c b/lib/libc/tests/gen/fmtcheck_test.c similarity index 84% rename from tools/regression/lib/libc/gen/test-fmtcheck.c rename to lib/libc/tests/gen/fmtcheck_test.c index 734eab1eac83..3e180c9ca2e6 100644 --- a/tools/regression/lib/libc/gen/test-fmtcheck.c +++ b/lib/libc/tests/gen/fmtcheck_test.c @@ -31,10 +31,13 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include +#include + struct test_fmt { char *fmt1; char *fmt2; @@ -72,31 +75,31 @@ struct test_fmt { { "%p %30s %#llx %-10.*e", "This number %lu%% and string %s has %qd numbers and %.*g floats", 1 }, }; -int -main(int argc, char *argv[]) +ATF_TC_WITHOUT_HEAD(fmtcheck_test); +ATF_TC_BODY(fmtcheck_test, tc) { - int i, n, r; - const char *f, *cf, *f1, *f2; + int i; + const char *f, *cf, *f1, *f2; - printf("1..1\n"); - r = 0; - n = sizeof(test_fmts) / sizeof(test_fmts[0]); - for (i=0 ; i __FBSDID("$FreeBSD$"); +#include #include - #include #include #include @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + static char *run_test(long classification, const char *label, int severity, const char *text, const char *action, const char *tag); @@ -217,18 +219,14 @@ run_test(long classification, const char *label, int severity, return (result); } -int -main(void) +ATF_TC_WITHOUT_HEAD(fmtmsg_test); +ATF_TC_BODY(fmtmsg_test, tc) { - size_t i, n; - int errors; char *result; struct testcase *t; + int i; - n = sizeof(testcases) / sizeof(testcases[0]); - errors = 0; - printf("1..%zu\n", n); - for (i = 0; i < n; i++) { + for (i = 0; i < nitems(testcases); i++) { t = &testcases[i]; if (t->msgverb != NULL) setenv("MSGVERB", t->msgverb, 1); @@ -236,16 +234,19 @@ main(void) unsetenv("MSGVERB"); result = run_test(t->classification, t->label, t->severity, t->text, t->action, t->tag); - if (result != NULL && strcmp(result, t->result) == 0) - printf("ok %zu - correct\n", - i + 1); - else { - printf("not ok %zu - %s\n", - i + 1, result != NULL ? "incorrect" : "failed"); - errors = 1; - } + ATF_CHECK_MSG(result != NULL, "testcase %d failed", i + 1); + if (result != NULL) + ATF_CHECK_MSG(strcmp(result, t->result) == 0, + "results for testcase %d didn't match; " + "`%s` != `%s`", i + 1, result, t->result); free(result); } - - return (errors); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fmtmsg_test); + + return (atf_no_error()); } diff --git a/lib/libc/tests/gen/fnmatch_test.c b/lib/libc/tests/gen/fnmatch_test.c new file mode 100644 index 000000000000..8d9ead2eff91 --- /dev/null +++ b/lib/libc/tests/gen/fnmatch_test.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2010 Jilles Tjoelker + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include + +#include "fnmatch_testcases.h" + +static const char * +flags_to_string(int flags) +{ + static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME, + FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 }; + static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0"; + static char result[sizeof(flagnames) + 3 * sizeof(int) + 2]; + char *p; + size_t i, len; + const char *fp; + + p = result; + fp = flagnames; + for (i = 0; flagvalues[i] != 0; i++) { + len = strlen(fp); + if (flags & flagvalues[i]) { + if (p != result) + *p++ = '|'; + memcpy(p, fp, len); + p += len; + flags &= ~flagvalues[i]; + } + fp += len + 1; + } + if (p == result) + memcpy(p, "0", 2); + else if (flags != 0) + sprintf(p, "%d", flags); + else + *p = '\0'; + return result; +} + +ATF_TC_WITHOUT_HEAD(fnmatch_test); +ATF_TC_BODY(fnmatch_test, tc) +{ + size_t i; + int flags, result; + struct testcase *t; + + for (i = 0; i < nitems(testcases); i++) { + t = &testcases[i]; + flags = t->flags; + do { + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + if (strchr(t->pattern, '\\') == NULL && + !(flags & FNM_NOESCAPE)) { + flags |= FNM_NOESCAPE; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if (strchr(t->pattern, '\\') != NULL && + strchr(t->string, '\\') == NULL && + t->result == FNM_NOMATCH && + !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) { + flags |= FNM_NOESCAPE; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((t->string[0] != '.' || t->pattern[0] == '.' || + t->result == FNM_NOMATCH) && + !(flags & (FNM_PATHNAME | FNM_PERIOD))) { + flags |= FNM_PERIOD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((strchr(t->string, '/') == NULL || + t->result == FNM_NOMATCH) && + !(flags & FNM_PATHNAME)) { + flags |= FNM_PATHNAME; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((((t->string[0] != '.' || t->pattern[0] == '.') && + strstr(t->string, "/.") == NULL) || + t->result == FNM_NOMATCH) && + flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) { + flags |= FNM_PERIOD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((((t->string[0] != '.' || t->pattern[0] == '.') && + strchr(t->string, '/') == NULL) || + t->result == FNM_NOMATCH) && + !(flags & (FNM_PATHNAME | FNM_PERIOD))) { + flags |= FNM_PATHNAME | FNM_PERIOD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if ((strchr(t->string, '/') == NULL || t->result == 0) + && !(flags & FNM_LEADING_DIR)) { + flags |= FNM_LEADING_DIR; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if (t->result == 0 && !(flags & FNM_CASEFOLD)) { + flags |= FNM_CASEFOLD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + if (strchr(t->pattern, '\\') == NULL && + t->result == 0 && + !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) { + flags |= FNM_NOESCAPE | FNM_CASEFOLD; + result = fnmatch(t->pattern, t->string, flags); + if (result != t->result) + break; + flags = t->flags; + } + } while (0); + + ATF_CHECK(result == t->result); + if (result == t->result) + printf("fnmatch(\"%s\", \"%s\", %s) == %d\n", + t->pattern, t->string, flags_to_string(flags), result); + else + printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n", + t->pattern, t->string, flags_to_string(flags), + t->result, result); + } + +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fnmatch_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fnmatch_testcases.h b/lib/libc/tests/gen/fnmatch_testcases.h new file mode 100644 index 000000000000..8e7c042b90bb --- /dev/null +++ b/lib/libc/tests/gen/fnmatch_testcases.h @@ -0,0 +1,176 @@ +/*- + * Copyright (c) 2010 Jilles Tjoelker + * 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 +__FBSDID("$FreeBSD$"); + +#include + +struct testcase { + const char *pattern; + const char *string; + int flags; + int result; +} testcases[] = { + "", "", 0, 0, + "a", "a", 0, 0, + "a", "b", 0, FNM_NOMATCH, + "a", "A", 0, FNM_NOMATCH, + "*", "a", 0, 0, + "*", "aa", 0, 0, + "*a", "a", 0, 0, + "*a", "b", 0, FNM_NOMATCH, + "*a*", "b", 0, FNM_NOMATCH, + "*a*b*", "ab", 0, 0, + "*a*b*", "qaqbq", 0, 0, + "*a*bb*", "qaqbqbbq", 0, 0, + "*a*bc*", "qaqbqbcq", 0, 0, + "*a*bb*", "qaqbqbb", 0, 0, + "*a*bc*", "qaqbqbc", 0, 0, + "*a*bb", "qaqbqbb", 0, 0, + "*a*bc", "qaqbqbc", 0, 0, + "*a*bb", "qaqbqbbq", 0, FNM_NOMATCH, + "*a*bc", "qaqbqbcq", 0, FNM_NOMATCH, + "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaa", 0, FNM_NOMATCH, + "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaa", 0, 0, + "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaaa", 0, 0, + ".*.*.*.*.*.*.*.*.*.*", ".........", 0, FNM_NOMATCH, + ".*.*.*.*.*.*.*.*.*.*", "..........", 0, 0, + ".*.*.*.*.*.*.*.*.*.*", "...........", 0, 0, + "*?*?*?*?*?*?*?*?*?*?*", "123456789", 0, FNM_NOMATCH, + "??????????*", "123456789", 0, FNM_NOMATCH, + "*??????????", "123456789", 0, FNM_NOMATCH, + "*?*?*?*?*?*?*?*?*?*?*", "1234567890", 0, 0, + "??????????*", "1234567890", 0, 0, + "*??????????", "1234567890", 0, 0, + "*?*?*?*?*?*?*?*?*?*?*", "12345678901", 0, 0, + "??????????*", "12345678901", 0, 0, + "*??????????", "12345678901", 0, 0, + "[x]", "x", 0, 0, + "[*]", "*", 0, 0, + "[?]", "?", 0, 0, + "[", "[", 0, 0, + "[[]", "[", 0, 0, + "[[]", "x", 0, FNM_NOMATCH, + "[*]", "", 0, FNM_NOMATCH, + "[*]", "x", 0, FNM_NOMATCH, + "[?]", "x", 0, FNM_NOMATCH, + "*[*]*", "foo*foo", 0, 0, + "*[*]*", "foo", 0, FNM_NOMATCH, + "[0-9]", "0", 0, 0, + "[0-9]", "5", 0, 0, + "[0-9]", "9", 0, 0, + "[0-9]", "/", 0, FNM_NOMATCH, + "[0-9]", ":", 0, FNM_NOMATCH, + "[0-9]", "*", 0, FNM_NOMATCH, + "[!0-9]", "0", 0, FNM_NOMATCH, + "[!0-9]", "5", 0, FNM_NOMATCH, + "[!0-9]", "9", 0, FNM_NOMATCH, + "[!0-9]", "/", 0, 0, + "[!0-9]", ":", 0, 0, + "[!0-9]", "*", 0, 0, + "*[0-9]", "a0", 0, 0, + "*[0-9]", "a5", 0, 0, + "*[0-9]", "a9", 0, 0, + "*[0-9]", "a/", 0, FNM_NOMATCH, + "*[0-9]", "a:", 0, FNM_NOMATCH, + "*[0-9]", "a*", 0, FNM_NOMATCH, + "*[!0-9]", "a0", 0, FNM_NOMATCH, + "*[!0-9]", "a5", 0, FNM_NOMATCH, + "*[!0-9]", "a9", 0, FNM_NOMATCH, + "*[!0-9]", "a/", 0, 0, + "*[!0-9]", "a:", 0, 0, + "*[!0-9]", "a*", 0, 0, + "*[0-9]", "a00", 0, 0, + "*[0-9]", "a55", 0, 0, + "*[0-9]", "a99", 0, 0, + "*[0-9]", "a0a0", 0, 0, + "*[0-9]", "a5a5", 0, 0, + "*[0-9]", "a9a9", 0, 0, + "\\*", "*", 0, 0, + "\\?", "?", 0, 0, + "\\[x]", "[x]", 0, 0, + "\\[", "[", 0, 0, + "\\\\", "\\", 0, 0, + "*\\**", "foo*foo", 0, 0, + "*\\**", "foo", 0, FNM_NOMATCH, + "*\\\\*", "foo\\foo", 0, 0, + "*\\\\*", "foo", 0, FNM_NOMATCH, + "\\(", "(", 0, 0, + "\\a", "a", 0, 0, + "\\*", "a", 0, FNM_NOMATCH, + "\\?", "a", 0, FNM_NOMATCH, + "\\*", "\\*", 0, FNM_NOMATCH, + "\\?", "\\?", 0, FNM_NOMATCH, + "\\[x]", "\\[x]", 0, FNM_NOMATCH, + "\\[x]", "\\x", 0, FNM_NOMATCH, + "\\[", "\\[", 0, FNM_NOMATCH, + "\\(", "\\(", 0, FNM_NOMATCH, + "\\a", "\\a", 0, FNM_NOMATCH, + "\\", "\\", 0, FNM_NOMATCH, + "\\", "", 0, 0, + "\\*", "\\*", FNM_NOESCAPE, 0, + "\\?", "\\?", FNM_NOESCAPE, 0, + "\\", "\\", FNM_NOESCAPE, 0, + "\\\\", "\\", FNM_NOESCAPE, FNM_NOMATCH, + "\\\\", "\\\\", FNM_NOESCAPE, 0, + "*\\*", "foo\\foo", FNM_NOESCAPE, 0, + "*\\*", "foo", FNM_NOESCAPE, FNM_NOMATCH, + "*", ".", FNM_PERIOD, FNM_NOMATCH, + "?", ".", FNM_PERIOD, FNM_NOMATCH, + ".*", ".", 0, 0, + ".*", "..", 0, 0, + ".*", ".a", 0, 0, + "[0-9]", ".", FNM_PERIOD, FNM_NOMATCH, + "a*", "a.", 0, 0, + "a/a", "a/a", FNM_PATHNAME, 0, + "a/*", "a/a", FNM_PATHNAME, 0, + "*/a", "a/a", FNM_PATHNAME, 0, + "*/*", "a/a", FNM_PATHNAME, 0, + "a*b/*", "abbb/x", FNM_PATHNAME, 0, + "a*b/*", "abbb/.x", FNM_PATHNAME, 0, + "*", "a/a", FNM_PATHNAME, FNM_NOMATCH, + "*/*", "a/a/a", FNM_PATHNAME, FNM_NOMATCH, + "b/*", "b/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, + "b*/*", "a/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, + "b/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0, + "b*/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0, + "a", "A", FNM_CASEFOLD, 0, + "A", "a", FNM_CASEFOLD, 0, + "[a]", "A", FNM_CASEFOLD, 0, + "[A]", "a", FNM_CASEFOLD, 0, + "a", "b", FNM_CASEFOLD, FNM_NOMATCH, + "a", "a/b", FNM_PATHNAME, FNM_NOMATCH, + "*", "a/b", FNM_PATHNAME, FNM_NOMATCH, + "*b", "a/b", FNM_PATHNAME, FNM_NOMATCH, + "a", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, + "*", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, + "*", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, + "*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, + "*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH, + "*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH, + "a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, +}; diff --git a/tools/regression/lib/libc/gen/test-ftw.c b/lib/libc/tests/gen/ftw_test.c similarity index 61% rename from tools/regression/lib/libc/gen/test-ftw.c rename to lib/libc/tests/gen/ftw_test.c index 209f033900b0..a778ecaaaccb 100644 --- a/tools/regression/lib/libc/gen/test-ftw.c +++ b/lib/libc/tests/gen/ftw_test.c @@ -32,50 +32,26 @@ __FBSDID("$FreeBSD$"); #include - -#include #include #include #include #include +#include #include #include #include #include #include +#include + extern char **environ; -static char dir[] = "/tmp/testftw.XXXXXXXXXX"; +static char template[] = "testftw.XXXXXXXXXX"; +static char dir[PATH_MAX]; static int failures; static int ftwflags; -static void -cleanup(int ustatus __unused) -{ - int error, status; - pid_t pid, waitres; - const char *myargs[5]; - - err_set_exit(NULL); - myargs[0] = "rm"; - myargs[1] = "-rf"; - myargs[2] = "--"; - myargs[3] = dir; - myargs[4] = NULL; - error = posix_spawnp(&pid, myargs[0], NULL, NULL, - __DECONST(char **, myargs), environ); - if (error != 0) - warn("posix_spawnp rm"); - else { - waitres = waitpid(pid, &status, 0); - if (waitres != pid) - warnx("waitpid rm failed"); - else if (status != 0) - warnx("rm failed"); - } -} - static int cb(const char *path, const struct stat *st, int type, struct FTW *f) { @@ -94,50 +70,59 @@ cb(const char *path, const struct stat *st, int type, struct FTW *f) return (0); break; } - warnx("unexpected path=%s type=%d f.level=%d\n", + ATF_CHECK_MSG(false, + "unexpected path=%s type=%d f.level=%d\n", path, type, f->level); - failures++; return (0); } -int -main(int argc, char *argv[]) +ATF_TC_WITHOUT_HEAD(ftw_test); +ATF_TC_BODY(ftw_test, tc) { int fd; - if (!mkdtemp(dir)) - err(2, "mkdtemp"); + ATF_REQUIRE_MSG(mkdtemp(template) != NULL, "mkdtemp failed"); - err_set_exit(cleanup); + /* XXX: the path needs to be absolute for the 0/FTW_DEPTH testcases */ + ATF_REQUIRE_MSG(realpath(template, dir) != NULL, + "realpath failed; errno=%d", errno); - fd = open(dir, O_DIRECTORY | O_RDONLY); - if (fd == -1) - err(2, "open %s", dir); + fd = open(dir, O_DIRECTORY|O_RDONLY); + ATF_REQUIRE_MSG(fd != -1, "open failed; errno=%d", errno); - if (mkdirat(fd, "d1", 0777) == -1) - err(2, "mkdirat d1"); + ATF_REQUIRE_MSG(mkdirat(fd, "d1", 0777) == 0, + "mkdirat failed; errno=%d", errno); - if (symlinkat(dir, fd, "d1/looper") == -1) - err(2, "symlinkat looper"); + ATF_REQUIRE_MSG(symlinkat(dir, fd, "d1/looper") == 0, + "symlinkat failed; errno=%d", errno); + printf("ftwflags=FTW_PHYS\n"); ftwflags = FTW_PHYS; - if (nftw(dir, cb, 10, ftwflags) == -1) - err(2, "nftw FTW_PHYS"); - ftwflags = FTW_PHYS | FTW_DEPTH; - if (nftw(dir, cb, 10, ftwflags) == -1) - err(2, "nftw FTW_PHYS | FTW_DEPTH"); + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw FTW_PHYS failed; errno=%d", errno); + + printf("ftwflags=FTW_PHYS|FTW_DEPTH\n"); + ftwflags = FTW_PHYS|FTW_DEPTH; + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw FTW_PHYS|FTW_DEPTH failed; errno=%d", errno); + + printf("ftwflags=0\n"); ftwflags = 0; - if (nftw(dir, cb, 10, ftwflags) == -1) - err(2, "nftw 0"); + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw 0 failed; errno=%d", errno); + + printf("ftwflags=FTW_DEPTH\n"); ftwflags = FTW_DEPTH; - if (nftw(dir, cb, 10, ftwflags) == -1) - err(2, "nftw FTW_DEPTH"); + ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1, + "nftw FTW_DEPTH failed; errno=%d", errno); close(fd); - - printf("PASS nftw()\n"); - - cleanup(failures != 0); - - return (failures != 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, ftw_test); + + return (atf_no_error()); } diff --git a/lib/libc/tests/gen/popen_test.c b/lib/libc/tests/gen/popen_test.c new file mode 100644 index 000000000000..73f72e193736 --- /dev/null +++ b/lib/libc/tests/gen/popen_test.c @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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. + */ + +/* + * Limited test program for popen() as specified by IEEE Std. 1003.1-2008, + * with BSD extensions. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static volatile sig_atomic_t got_sigpipe; + +static void +sigpipe_handler(int sig __unused) +{ + got_sigpipe = 1; +} + +static void +check_cloexec(FILE *fp, const char *mode) +{ + int exp_flags, flags; + + flags = fcntl(fileno(fp), F_GETFD); + ATF_CHECK_MSG(flags != -1, "fcntl(F_GETFD) failed; errno=%d", errno); + if (flags == -1) + return; + if (strchr(mode, 'e') != NULL) + exp_flags = FD_CLOEXEC; + else + exp_flags = 0; + ATF_CHECK_MSG((flags & FD_CLOEXEC) == exp_flags, + "bad cloexec flag; %d != %d", flags, exp_flags); +} + +ATF_TC_WITHOUT_HEAD(popen_all_modes_test); +ATF_TC_BODY(popen_all_modes_test, tc) +{ + FILE *fp, *fp2; + int i, status; + const char *mode; + const char *allmodes[] = { "r", "w", "r+", "re", "we", "r+e", "re+" }; + + for (i = 0; i < nitems(allmodes); i++) { + mode = allmodes[i]; + fp = popen("exit 7", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 7, + "bad exit status (no I/O)"); + } +} + +ATF_TC_WITHOUT_HEAD(popen_rmodes_test); +ATF_TC_BODY(popen_rmodes_test, tc) +{ + FILE *fp, *fp2; + const char *rmodes[] = { "r", "r+", "re", "r+e", "re+" }; + const char *mode; + char buf[80]; + int i, status; + + for (i = 0; i < nitems(rmodes); i++) { + mode = rmodes[i]; + fp = popen("exit 9", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + bool input_error_1 = !(fgetc(fp) != EOF || !feof(fp) || !ferror(fp)); + ATF_CHECK_MSG(!input_error_1, "input error 1"); + if (input_error_1) + continue; + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 9, + "bad exit status (input)"); + } + + for (i = 0; i < nitems(rmodes); i++) { + char *sres; + mode = rmodes[i]; + fp = popen("echo hi there", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + ATF_CHECK_MSG((sres = fgets(buf, sizeof(buf), fp)) != NULL, + "Input error 2"); + if (sres != NULL) + ATF_CHECK_MSG(strcmp(buf, "hi there\n") == 0, + "Bad input 1"); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0, + "Bad exit status (input)"); + } +} + +ATF_TC_WITHOUT_HEAD(popen_wmodes_test); +ATF_TC_BODY(popen_wmodes_test, tc) +{ + FILE *fp, *fp2; + const char *wmodes[] = { "w", "r+", "we", "r+e", "re+" }; + const char *mode; + struct sigaction act, oact; + int i, j, status; + + for (i = 0; i < nitems(wmodes); i++) { + mode = wmodes[i]; + fp = popen("read x && [ \"$x\" = abcd ]", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + ATF_CHECK_MSG(fputs("abcd\n", fp) != EOF, + "Output error 1"); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0, + "Bad exit status (output)"); + } + + act.sa_handler = sigpipe_handler; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + ATF_CHECK_MSG(sigaction(SIGPIPE, &act, &oact) != -1, + "sigaction() failed"); + for (i = 0; i < nitems(wmodes); i++) { + mode = wmodes[i]; + fp = popen("exit 88", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + got_sigpipe = 0; + while (fputs("abcd\n", fp) != EOF) + ; + ATF_CHECK_MSG(ferror(fp) && errno == EPIPE, "Expected EPIPE"); + ATF_CHECK_MSG(got_sigpipe, "Expected SIGPIPE"); + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 88, + "Bad exit status (EPIPE)"); + } + ATF_CHECK_MSG(sigaction(SIGPIPE, &oact, NULL) != -1, + "sigaction() failed"); + + for (i = 0; i < nitems(wmodes); i++) { + for (j = 0; j < nitems(wmodes); j++) { + mode = wmodes[i]; + fp = popen("read x", mode); + ATF_CHECK_MSG(fp != NULL, + "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + mode = wmodes[j]; + fp2 = popen("read x", mode); + ATF_CHECK_MSG(fp2 != NULL, + "popen(, \"%s\") failed", mode); + if (fp2 == NULL) { + pclose(fp); + continue; + } + /* If fp2 inherits fp's pipe, we will deadlock here. */ + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 1, + "bad exit status (2 pipes)"); + status = pclose(fp2); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 1, + "bad exit status (2 pipes)"); + } + } +} + +ATF_TC_WITHOUT_HEAD(popen_rwmodes_test); +ATF_TC_BODY(popen_rwmodes_test, tc) +{ + const char *rwmodes[] = { "r+", "r+e", "re+" }; + FILE *fp, *fp2; + const char *mode; + char *sres; + char buf[80]; + int i, ires, status; + + for (i = 0; i < nitems(rwmodes); i++) { + mode = rwmodes[i]; + fp = popen("read x && printf '%s\\n' \"Q${x#a}\"", mode); + ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode); + if (fp == NULL) + continue; + check_cloexec(fp, mode); + ATF_CHECK_MSG((ires = fputs("abcd\n", fp)) != EOF, + "Output error 2"); + if (ires != EOF) { + sres = fgets(buf, sizeof(buf), fp); + ATF_CHECK_MSG(sres != NULL, "Input error 3"); + if (sres != NULL) + ATF_CHECK_MSG(strcmp(buf, "Qbcd\n") == 0, + "Bad input 2"); + } + status = pclose(fp); + ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0, + "bad exit status (I/O)"); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, popen_all_modes_test); + ATF_TP_ADD_TC(tp, popen_rmodes_test); + ATF_TP_ADD_TC(tp, popen_wmodes_test); + ATF_TP_ADD_TC(tp, popen_rwmodes_test); + + return (atf_no_error()); +} diff --git a/tools/regression/lib/libc/gen/test-posix_spawn.c b/lib/libc/tests/gen/posix_spawn_test.c similarity index 73% rename from tools/regression/lib/libc/gen/test-posix_spawn.c rename to lib/libc/tests/gen/posix_spawn_test.c index f1b8d4326817..e04d103e1a30 100644 --- a/tools/regression/lib/libc/gen/test-posix_spawn.c +++ b/lib/libc/tests/gen/posix_spawn_test.c @@ -33,26 +33,27 @@ __FBSDID("$FreeBSD$"); #include - -#include #include #include #include #include #include -int -main(int argc, char *argv[]) +#include + +char *myenv[2] = { "answer=42", NULL }; + +ATF_TC_WITHOUT_HEAD(posix_spawn_simple_test); +ATF_TC_BODY(posix_spawn_simple_test, tc) { + char *myargs[4]; int error, status; pid_t pid, waitres; - char *myargs[4]; - char *myenv[2] = { "answer=42", NULL }; /* Make sure we have no child processes. */ while (waitpid(-1, NULL, 0) != -1) ; - assert(errno == ECHILD); + ATF_REQUIRE_MSG(errno == ECHILD, "errno was not ECHILD: %d", errno); /* Simple test. */ myargs[0] = "sh"; @@ -60,10 +61,18 @@ main(int argc, char *argv[]) myargs[2] = "exit $answer"; myargs[3] = NULL; error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv); - assert(error == 0); + ATF_REQUIRE(error == 0); waitres = waitpid(pid, &status, 0); - assert(waitres == pid); - assert(WIFEXITED(status) && WEXITSTATUS(status) == 42); + ATF_REQUIRE(waitres == pid); + ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42); +} + +ATF_TC_WITHOUT_HEAD(posix_spawn_no_such_command_negative_test); +ATF_TC_BODY(posix_spawn_no_such_command_negative_test, tc) +{ + char *myargs[4]; + int error, status; + pid_t pid, waitres; /* * If the executable does not exist, the function shall either fail @@ -75,16 +84,20 @@ main(int argc, char *argv[]) error = posix_spawn(&pid, myargs[0], NULL, NULL, myargs, myenv); if (error == 0) { waitres = waitpid(pid, &status, 0); - assert(waitres == pid); - assert(WIFEXITED(status) && WEXITSTATUS(status) == 127); + ATF_REQUIRE(waitres == pid); + ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 127); } else { - assert(error == ENOENT); + ATF_REQUIRE(error == ENOENT); waitres = waitpid(-1, NULL, 0); - assert(waitres == -1 && errno == ECHILD); + ATF_REQUIRE(waitres == -1 && errno == ECHILD); } - - printf("PASS posix_spawn()\n"); - printf("PASS posix_spawnp()\n"); - - return (0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, posix_spawn_simple_test); + ATF_TP_ADD_TC(tp, posix_spawn_no_such_command_negative_test); + + return (atf_no_error()); } diff --git a/lib/libc/tests/gen/test-fnmatch.c b/lib/libc/tests/gen/test-fnmatch.c new file mode 100644 index 000000000000..e54613149c51 --- /dev/null +++ b/lib/libc/tests/gen/test-fnmatch.c @@ -0,0 +1,77 @@ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "fnmatch_testcases.h" + +static int +write_sh_tests(const char *progname, int num) +{ + size_t i; + struct testcase *t; + + printf("# Generated by %s -s %d, do not edit.\n", progname, num); + printf("# $" "FreeBSD$\n"); + printf("failures=\n"); + printf("failed() { printf '%%s\\n' \"Failed: $1 '$2' '$3'\"; failures=x$failures; }\n"); + if (num == 1) { + printf("testmatch() { eval \"case \\$2 in ''$1) ;; *) failed testmatch \\\"\\$@\\\";; esac\"; }\n"); + printf("testnomatch() { eval \"case \\$2 in ''$1) failed testnomatch \\\"\\$@\\\";; esac\"; }\n"); + } else if (num == 2) { + printf("# We do not treat a backslash specially in this case,\n"); + printf("# but this is not the case in all shells.\n"); + printf("netestmatch() { case $2 in $1) ;; *) failed netestmatch \"$@\";; esac; }\n"); + printf("netestnomatch() { case $2 in $1) failed netestnomatch \"$@\";; esac; }\n"); + } + + for (i = 0; i < nitems(testcases); i++) { + t = &testcases[i]; + if (strchr(t->pattern, '\'') != NULL || + strchr(t->string, '\'') != NULL) + continue; + if (t->flags == 0 && strcmp(t->pattern, "\\") == 0) + continue; + if (num == 1 && t->flags == 0) + printf("test%smatch '%s' '%s'\n", + t->result == FNM_NOMATCH ? "no" : "", + t->pattern, t->string); + if (num == 2 && (t->flags == FNM_NOESCAPE || + (t->flags == 0 && strchr(t->pattern, '\\') == NULL))) + printf("netest%smatch '%s' '%s'\n", + t->result == FNM_NOMATCH ? "no" : "", + t->pattern, t->string); + } + printf("[ -z \"$failures\" ]\n"); + return 0; +} + +static void +usage(char *progname) +{ + fprintf(stderr, "usage: %s [-s num]\n", progname); + fprintf(stderr, "-s option writes tests for sh(1), num is 1 or 2\n"); +} + +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "s:")) != -1) { + switch (opt) { + case 's': + return (write_sh_tests(argv[0], atoi(optarg))); + default: + usage(argv[0]); + exit(1); + } + } + usage(argv[0]); + exit(1); +} diff --git a/lib/libc/tests/gen/wordexp_test.c b/lib/libc/tests/gen/wordexp_test.c new file mode 100644 index 000000000000..3ccc67774c7f --- /dev/null +++ b/lib/libc/tests/gen/wordexp_test.c @@ -0,0 +1,360 @@ +/*- + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include + +static void +chld_handler(int x) +{ + int status, serrno; + + (void)x; + serrno = errno; + while (waitpid(-1, &status, WNOHANG) > 0) + ; + errno = serrno; +} + +ATF_TC_WITHOUT_HEAD(simple_test); +ATF_TC_BODY(simple_test, tc) +{ + wordexp_t we; + int r; + + /* Test that the macros are there. */ + (void)(WRDE_APPEND + WRDE_DOOFFS + 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); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(long_output_test); +ATF_TC_BODY(long_output_test, tc) +{ + char longdata[6 * 10000 + 1]; + wordexp_t we; + int i, r; + + /* Long output. */ + for (i = 0; i < 10000; i++) + snprintf(longdata + 6 * i, 7, "%05d ", i); + r = wordexp(longdata, &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 10000); + ATF_REQUIRE(we.we_wordv[10000] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS_test); +ATF_TC_BODY(WRDE_DOOFFS_test, tc) +{ + wordexp_t we; + int r; + + we.we_offs = 3; + r = wordexp("hello world", &we, WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(we.we_wordv[0] == NULL); + ATF_REQUIRE(we.we_wordv[1] == NULL); + ATF_REQUIRE(we.we_wordv[2] == NULL); + ATF_REQUIRE(strcmp(we.we_wordv[3], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[4], "world") == 0); + ATF_REQUIRE(we.we_wordv[5] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_REUSE_test); +ATF_TC_BODY(WRDE_REUSE_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("hello world", &we, 0); + r = wordexp("hello world", &we, WRDE_REUSE); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_APPEND_test); +ATF_TC_BODY(WRDE_APPEND_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("this is", &we, 0); + ATF_REQUIRE(r == 0); + r = wordexp("a test", &we, WRDE_APPEND); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 4); + ATF_REQUIRE(strcmp(we.we_wordv[0], "this") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "is") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[2], "a") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[3], "test") == 0); + ATF_REQUIRE(we.we_wordv[4] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS__WRDE_APPEND_test); +ATF_TC_BODY(WRDE_DOOFFS__WRDE_APPEND_test, tc) +{ + wordexp_t we; + int r; + + we.we_offs = 2; + r = wordexp("this is", &we, WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFFS); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 6); + ATF_REQUIRE(we.we_wordv[0] == NULL); + ATF_REQUIRE(we.we_wordv[1] == NULL); + ATF_REQUIRE(strcmp(we.we_wordv[2], "this") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[3], "is") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[4], "a") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[5], "test") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[6], "of") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[7], "wordexp") == 0); + ATF_REQUIRE(we.we_wordv[8] == NULL); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_UNDEF_test); +ATF_TC_BODY(WRDE_UNDEF_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("${dont_set_me}", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_BADVAL); +} + +ATF_TC_WITHOUT_HEAD(WRDE_NOCMD_test); +ATF_TC_BODY(WRDE_NOCMD_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("`date`", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("\"`date`\"", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("$(date)", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("\"$(date)\"", &we, WRDE_NOCMD); + ATF_REQUIRE(r == WRDE_CMDSUB); + r = wordexp("$((3+5))", &we, WRDE_NOCMD); + ATF_REQUIRE(r == 0); + r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE); + ATF_REQUIRE(r == 0); + r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE); + ATF_REQUIRE(r == 0); + r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE); + ATF_REQUIRE(r == 0); + wordfree(&we); +} + +ATF_TC_WITHOUT_HEAD(WRDE_BADCHAR_test); +ATF_TC_BODY(WRDE_BADCHAR_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("'\n|&;<>(){}'", &we, 0); + ATF_REQUIRE(r == 0); + r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE); + ATF_REQUIRE(r == 0); + r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE); + ATF_REQUIRE(r == 0); + wordfree(&we); + r = wordexp("test \n test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test | test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test & test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test ; test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test > test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test < test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test ( test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test ) test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test { test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); + r = wordexp("test } test", &we, 0); + ATF_REQUIRE(r == WRDE_BADCHAR); +} + +ATF_TC_WITHOUT_HEAD(WRDE_SYNTAX_test); +ATF_TC_BODY(WRDE_SYNTAX_test, tc) +{ + wordexp_t we; + int r; + + r = wordexp("'", &we, 0); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("'", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("'\\'", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 1); + ATF_REQUIRE(strcmp(we.we_wordv[0], "\\") == 0); + ATF_REQUIRE(we.we_wordv[1] == NULL); + wordfree(&we); + /* Two syntax errors that are not detected by the current we_check(). */ + r = wordexp("${IFS:+'}", &we, 0); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("${IFS:+'}", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("$(case)", &we, 0); + ATF_REQUIRE(r == WRDE_SYNTAX); + r = wordexp("$(case)", &we, WRDE_UNDEF); + ATF_REQUIRE(r == WRDE_SYNTAX); +} + +ATF_TC_WITHOUT_HEAD(with_SIGCHILD_handler_test); +ATF_TC_BODY(with_SIGCHILD_handler_test, tc) +{ + struct sigaction sa; + wordexp_t we; + int r; + + /* With a SIGCHLD handler that reaps all zombies. */ + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = chld_handler; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + sa.sa_handler = SIG_DFL; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); +} + +ATF_TC_WITHOUT_HEAD(with_unused_non_default_IFS_test); +ATF_TC_BODY(with_unused_non_default_IFS_test, tc) +{ + wordexp_t we; + int r; + + /* + * With IFS set to a non-default value (without depending on whether + * IFS is inherited or not). + */ + r = setenv("IFS", ":", 1); + ATF_REQUIRE(r == 0); + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + r = unsetenv("IFS"); + ATF_REQUIRE(r == 0); +} + +ATF_TC_WITHOUT_HEAD(with_used_non_default_IFS_test); +ATF_TC_BODY(with_used_non_default_IFS_test, tc) +{ + wordexp_t we; + int r; + + /* + * With IFS set to a non-default value, and using it. + */ + r = setenv("IFS", ":", 1); + ATF_REQUIRE(r == 0); + r = wordexp("${IFS+hello:world}", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + r = unsetenv("IFS"); + ATF_REQUIRE(r == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, simple_test); + ATF_TP_ADD_TC(tp, long_output_test); + ATF_TP_ADD_TC(tp, WRDE_DOOFFS_test); + ATF_TP_ADD_TC(tp, WRDE_REUSE_test); + ATF_TP_ADD_TC(tp, WRDE_APPEND_test); + ATF_TP_ADD_TC(tp, WRDE_DOOFFS__WRDE_APPEND_test); + ATF_TP_ADD_TC(tp, WRDE_UNDEF_test); + ATF_TP_ADD_TC(tp, WRDE_NOCMD_test); + ATF_TP_ADD_TC(tp, WRDE_BADCHAR_test); + ATF_TP_ADD_TC(tp, WRDE_SYNTAX_test); + ATF_TP_ADD_TC(tp, with_SIGCHILD_handler_test); + ATF_TP_ADD_TC(tp, with_unused_non_default_IFS_test); + ATF_TP_ADD_TC(tp, with_used_non_default_IFS_test); + + return (atf_no_error()); +} diff --git a/tools/regression/lib/libc/gen/Makefile b/tools/regression/lib/libc/gen/Makefile deleted file mode 100644 index f3a40e351d90..000000000000 --- a/tools/regression/lib/libc/gen/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# $FreeBSD$ - -TESTS= test-fmtcheck test-fmtmsg test-fnmatch \ - test-ftw test-popen test-posix_spawn test-wordexp - -.PHONY: tests -tests: ${TESTS} - for p in ${TESTS}; do ${.OBJDIR}/$$p; done - -.PHONY: clean -clean: - -rm -f ${TESTS} - -sh-tests: test-fnmatch - ./test-fnmatch -s 1 >../../../bin/sh/builtins/case2.0 - ./test-fnmatch -s 2 >../../../bin/sh/builtins/case3.0 diff --git a/tools/regression/lib/libc/gen/test-fnmatch.c b/tools/regression/lib/libc/gen/test-fnmatch.c deleted file mode 100644 index fd33574643ef..000000000000 --- a/tools/regression/lib/libc/gen/test-fnmatch.c +++ /dev/null @@ -1,390 +0,0 @@ -/*- - * Copyright (c) 2010 Jilles Tjoelker - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -struct testcase { - const char *pattern; - const char *string; - int flags; - int result; -} testcases[] = { - "", "", 0, 0, - "a", "a", 0, 0, - "a", "b", 0, FNM_NOMATCH, - "a", "A", 0, FNM_NOMATCH, - "*", "a", 0, 0, - "*", "aa", 0, 0, - "*a", "a", 0, 0, - "*a", "b", 0, FNM_NOMATCH, - "*a*", "b", 0, FNM_NOMATCH, - "*a*b*", "ab", 0, 0, - "*a*b*", "qaqbq", 0, 0, - "*a*bb*", "qaqbqbbq", 0, 0, - "*a*bc*", "qaqbqbcq", 0, 0, - "*a*bb*", "qaqbqbb", 0, 0, - "*a*bc*", "qaqbqbc", 0, 0, - "*a*bb", "qaqbqbb", 0, 0, - "*a*bc", "qaqbqbc", 0, 0, - "*a*bb", "qaqbqbbq", 0, FNM_NOMATCH, - "*a*bc", "qaqbqbcq", 0, FNM_NOMATCH, - "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaa", 0, FNM_NOMATCH, - "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaa", 0, 0, - "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaaa", 0, 0, - ".*.*.*.*.*.*.*.*.*.*", ".........", 0, FNM_NOMATCH, - ".*.*.*.*.*.*.*.*.*.*", "..........", 0, 0, - ".*.*.*.*.*.*.*.*.*.*", "...........", 0, 0, - "*?*?*?*?*?*?*?*?*?*?*", "123456789", 0, FNM_NOMATCH, - "??????????*", "123456789", 0, FNM_NOMATCH, - "*??????????", "123456789", 0, FNM_NOMATCH, - "*?*?*?*?*?*?*?*?*?*?*", "1234567890", 0, 0, - "??????????*", "1234567890", 0, 0, - "*??????????", "1234567890", 0, 0, - "*?*?*?*?*?*?*?*?*?*?*", "12345678901", 0, 0, - "??????????*", "12345678901", 0, 0, - "*??????????", "12345678901", 0, 0, - "[x]", "x", 0, 0, - "[*]", "*", 0, 0, - "[?]", "?", 0, 0, - "[", "[", 0, 0, - "[[]", "[", 0, 0, - "[[]", "x", 0, FNM_NOMATCH, - "[*]", "", 0, FNM_NOMATCH, - "[*]", "x", 0, FNM_NOMATCH, - "[?]", "x", 0, FNM_NOMATCH, - "*[*]*", "foo*foo", 0, 0, - "*[*]*", "foo", 0, FNM_NOMATCH, - "[0-9]", "0", 0, 0, - "[0-9]", "5", 0, 0, - "[0-9]", "9", 0, 0, - "[0-9]", "/", 0, FNM_NOMATCH, - "[0-9]", ":", 0, FNM_NOMATCH, - "[0-9]", "*", 0, FNM_NOMATCH, - "[!0-9]", "0", 0, FNM_NOMATCH, - "[!0-9]", "5", 0, FNM_NOMATCH, - "[!0-9]", "9", 0, FNM_NOMATCH, - "[!0-9]", "/", 0, 0, - "[!0-9]", ":", 0, 0, - "[!0-9]", "*", 0, 0, - "*[0-9]", "a0", 0, 0, - "*[0-9]", "a5", 0, 0, - "*[0-9]", "a9", 0, 0, - "*[0-9]", "a/", 0, FNM_NOMATCH, - "*[0-9]", "a:", 0, FNM_NOMATCH, - "*[0-9]", "a*", 0, FNM_NOMATCH, - "*[!0-9]", "a0", 0, FNM_NOMATCH, - "*[!0-9]", "a5", 0, FNM_NOMATCH, - "*[!0-9]", "a9", 0, FNM_NOMATCH, - "*[!0-9]", "a/", 0, 0, - "*[!0-9]", "a:", 0, 0, - "*[!0-9]", "a*", 0, 0, - "*[0-9]", "a00", 0, 0, - "*[0-9]", "a55", 0, 0, - "*[0-9]", "a99", 0, 0, - "*[0-9]", "a0a0", 0, 0, - "*[0-9]", "a5a5", 0, 0, - "*[0-9]", "a9a9", 0, 0, - "\\*", "*", 0, 0, - "\\?", "?", 0, 0, - "\\[x]", "[x]", 0, 0, - "\\[", "[", 0, 0, - "\\\\", "\\", 0, 0, - "*\\**", "foo*foo", 0, 0, - "*\\**", "foo", 0, FNM_NOMATCH, - "*\\\\*", "foo\\foo", 0, 0, - "*\\\\*", "foo", 0, FNM_NOMATCH, - "\\(", "(", 0, 0, - "\\a", "a", 0, 0, - "\\*", "a", 0, FNM_NOMATCH, - "\\?", "a", 0, FNM_NOMATCH, - "\\*", "\\*", 0, FNM_NOMATCH, - "\\?", "\\?", 0, FNM_NOMATCH, - "\\[x]", "\\[x]", 0, FNM_NOMATCH, - "\\[x]", "\\x", 0, FNM_NOMATCH, - "\\[", "\\[", 0, FNM_NOMATCH, - "\\(", "\\(", 0, FNM_NOMATCH, - "\\a", "\\a", 0, FNM_NOMATCH, - "\\", "\\", 0, FNM_NOMATCH, - "\\", "", 0, 0, - "\\*", "\\*", FNM_NOESCAPE, 0, - "\\?", "\\?", FNM_NOESCAPE, 0, - "\\", "\\", FNM_NOESCAPE, 0, - "\\\\", "\\", FNM_NOESCAPE, FNM_NOMATCH, - "\\\\", "\\\\", FNM_NOESCAPE, 0, - "*\\*", "foo\\foo", FNM_NOESCAPE, 0, - "*\\*", "foo", FNM_NOESCAPE, FNM_NOMATCH, - "*", ".", FNM_PERIOD, FNM_NOMATCH, - "?", ".", FNM_PERIOD, FNM_NOMATCH, - ".*", ".", 0, 0, - ".*", "..", 0, 0, - ".*", ".a", 0, 0, - "[0-9]", ".", FNM_PERIOD, FNM_NOMATCH, - "a*", "a.", 0, 0, - "a/a", "a/a", FNM_PATHNAME, 0, - "a/*", "a/a", FNM_PATHNAME, 0, - "*/a", "a/a", FNM_PATHNAME, 0, - "*/*", "a/a", FNM_PATHNAME, 0, - "a*b/*", "abbb/x", FNM_PATHNAME, 0, - "a*b/*", "abbb/.x", FNM_PATHNAME, 0, - "*", "a/a", FNM_PATHNAME, FNM_NOMATCH, - "*/*", "a/a/a", FNM_PATHNAME, FNM_NOMATCH, - "b/*", "b/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, - "b*/*", "a/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, - "b/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0, - "b*/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0, - "a", "A", FNM_CASEFOLD, 0, - "A", "a", FNM_CASEFOLD, 0, - "[a]", "A", FNM_CASEFOLD, 0, - "[A]", "a", FNM_CASEFOLD, 0, - "a", "b", FNM_CASEFOLD, FNM_NOMATCH, - "a", "a/b", FNM_PATHNAME, FNM_NOMATCH, - "*", "a/b", FNM_PATHNAME, FNM_NOMATCH, - "*b", "a/b", FNM_PATHNAME, FNM_NOMATCH, - "a", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, - "*", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, - "*", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, - "*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0, - "*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH, - "*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH, - "a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH, -}; - -static const char * -flags_to_string(int flags) -{ - static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME, - FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 }; - static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0"; - static char result[sizeof(flagnames) + 3 * sizeof(int) + 2]; - char *p; - size_t i, len; - const char *fp; - - p = result; - fp = flagnames; - for (i = 0; flagvalues[i] != 0; i++) { - len = strlen(fp); - if (flags & flagvalues[i]) { - if (p != result) - *p++ = '|'; - memcpy(p, fp, len); - p += len; - flags &= ~flagvalues[i]; - } - fp += len + 1; - } - if (p == result) - memcpy(p, "0", 2); - else if (flags != 0) - sprintf(p, "%d", flags); - else - *p = '\0'; - return result; -} - -static int -write_sh_tests(const char *progname, int num) -{ - size_t i, n; - struct testcase *t; - - printf("# Generated by %s -s %d, do not edit.\n", progname, num); - printf("# $" "FreeBSD$\n"); - printf("failures=\n"); - printf("failed() { printf '%%s\\n' \"Failed: $1 '$2' '$3'\"; failures=x$failures; }\n"); - if (num == 1) { - printf("testmatch() { eval \"case \\$2 in ''$1) ;; *) failed testmatch \\\"\\$@\\\";; esac\"; }\n"); - printf("testnomatch() { eval \"case \\$2 in ''$1) failed testnomatch \\\"\\$@\\\";; esac\"; }\n"); - } else if (num == 2) { - printf("# We do not treat a backslash specially in this case,\n"); - printf("# but this is not the case in all shells.\n"); - printf("netestmatch() { case $2 in $1) ;; *) failed netestmatch \"$@\";; esac; }\n"); - printf("netestnomatch() { case $2 in $1) failed netestnomatch \"$@\";; esac; }\n"); - } - n = sizeof(testcases) / sizeof(testcases[0]); - for (i = 0; i < n; i++) { - t = &testcases[i]; - if (strchr(t->pattern, '\'') != NULL || - strchr(t->string, '\'') != NULL) - continue; - if (t->flags == 0 && strcmp(t->pattern, "\\") == 0) - continue; - if (num == 1 && t->flags == 0) - printf("test%smatch '%s' '%s'\n", - t->result == FNM_NOMATCH ? "no" : "", - t->pattern, t->string); - if (num == 2 && (t->flags == FNM_NOESCAPE || - (t->flags == 0 && strchr(t->pattern, '\\') == NULL))) - printf("netest%smatch '%s' '%s'\n", - t->result == FNM_NOMATCH ? "no" : "", - t->pattern, t->string); - } - printf("[ -z \"$failures\" ]\n"); - return 0; -} - -int -main(int argc, char *argv[]) -{ - size_t i, n; - int opt, flags, result, extra, errors; - struct testcase *t; - - while ((opt = getopt(argc, argv, "s:")) != -1) { - switch (opt) { - case 's': - return (write_sh_tests(argv[0], atoi(optarg))); - default: - fprintf(stderr, "usage: %s [-s num]\n", argv[0]); - fprintf(stderr, "-s option writes tests for sh(1), num is 1 or 2\n"); - exit(1); - } - } - n = sizeof(testcases) / sizeof(testcases[0]); - errors = 0; - printf("1..%zu\n", n); - for (i = 0; i < n; i++) { - t = &testcases[i]; - flags = t->flags; - extra = 0; - do { - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - if (strchr(t->pattern, '\\') == NULL && - !(flags & FNM_NOESCAPE)) { - flags |= FNM_NOESCAPE; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if (strchr(t->pattern, '\\') != NULL && - strchr(t->string, '\\') == NULL && - t->result == FNM_NOMATCH && - !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) { - flags |= FNM_NOESCAPE; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if ((t->string[0] != '.' || t->pattern[0] == '.' || - t->result == FNM_NOMATCH) && - !(flags & (FNM_PATHNAME | FNM_PERIOD))) { - flags |= FNM_PERIOD; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if ((strchr(t->string, '/') == NULL || - t->result == FNM_NOMATCH) && - !(flags & FNM_PATHNAME)) { - flags |= FNM_PATHNAME; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if ((((t->string[0] != '.' || t->pattern[0] == '.') && - strstr(t->string, "/.") == NULL) || - t->result == FNM_NOMATCH) && - flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) { - flags |= FNM_PERIOD; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if ((((t->string[0] != '.' || t->pattern[0] == '.') && - strchr(t->string, '/') == NULL) || - t->result == FNM_NOMATCH) && - !(flags & (FNM_PATHNAME | FNM_PERIOD))) { - flags |= FNM_PATHNAME | FNM_PERIOD; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if ((strchr(t->string, '/') == NULL || t->result == 0) - && !(flags & FNM_LEADING_DIR)) { - flags |= FNM_LEADING_DIR; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if (t->result == 0 && !(flags & FNM_CASEFOLD)) { - flags |= FNM_CASEFOLD; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - if (strchr(t->pattern, '\\') == NULL && - t->result == 0 && - !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) { - flags |= FNM_NOESCAPE | FNM_CASEFOLD; - result = fnmatch(t->pattern, t->string, flags); - if (result != t->result) - break; - flags = t->flags; - extra++; - } - } while (0); - if (result == t->result) - printf("ok %zu - fnmatch(\"%s\", \"%s\", %s) = %d (+%d)\n", - i + 1, t->pattern, t->string, - flags_to_string(flags), - result, extra); - else { - printf("not ok %zu - fnmatch(\"%s\", \"%s\", %s) = %d != %d\n", - i + 1, t->pattern, t->string, - flags_to_string(flags), - result, t->result); - errors = 1; - } - } - - return (errors); -} diff --git a/tools/regression/lib/libc/gen/test-popen.c b/tools/regression/lib/libc/gen/test-popen.c deleted file mode 100644 index bf301d2f970c..000000000000 --- a/tools/regression/lib/libc/gen/test-popen.c +++ /dev/null @@ -1,227 +0,0 @@ -/*- - * Copyright (c) 2013 Jilles Tjoelker - * 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. - */ - -/* - * Limited test program for popen() as specified by IEEE Std. 1003.1-2008, - * with BSD extensions. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include -#include -#include - -static int failures; -static volatile sig_atomic_t got_sigpipe; - -static void -sigpipe_handler(int sig __unused) -{ - got_sigpipe = 1; -} - -static void -check_cloexec(FILE *fp, const char *mode) -{ - int flags; - - flags = fcntl(fileno(fp), F_GETFD); - if (flags == -1) - fprintf(stderr, "fcntl(F_GETFD) failed\n"), failures++; - else if ((flags & FD_CLOEXEC) != - (strchr(mode, 'e') != NULL ? FD_CLOEXEC : 0)) - fprintf(stderr, "Bad cloexec flag\n"), failures++; -} - -int -main(int argc, char *argv[]) -{ - FILE *fp, *fp2; - int i, j, status; - const char *mode; - const char *allmodes[] = { "r", "w", "r+", "re", "we", "r+e", "re+" }; - const char *rmodes[] = { "r", "r+", "re", "r+e", "re+" }; - const char *wmodes[] = { "w", "r+", "we", "r+e", "re+" }; - const char *rwmodes[] = { "r+", "r+e", "re+" }; - char buf[80]; - struct sigaction act, oact; - - for (i = 0; i < sizeof(allmodes) / sizeof(allmodes[0]); i++) { - mode = allmodes[i]; - fp = popen("exit 7", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - check_cloexec(fp, mode); - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 7) - fprintf(stderr, "Bad exit status (no I/O)\n"), failures++; - } - - for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { - mode = rmodes[i]; - fp = popen("exit 9", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - check_cloexec(fp, mode); - if (fgetc(fp) != EOF || !feof(fp) || ferror(fp)) - fprintf(stderr, "Input error 1\n"), failures++; - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 9) - fprintf(stderr, "Bad exit status (input)\n"), failures++; - } - - for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { - mode = rmodes[i]; - fp = popen("echo hi there", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - check_cloexec(fp, mode); - if (fgets(buf, sizeof(buf), fp) == NULL) - fprintf(stderr, "Input error 2\n"), failures++; - else if (strcmp(buf, "hi there\n") != 0) - fprintf(stderr, "Bad input 1\n"), failures++; - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - fprintf(stderr, "Bad exit status (input)\n"), failures++; - } - - for (i = 0; i < sizeof(wmodes) / sizeof(wmodes[0]); i++) { - mode = wmodes[i]; - fp = popen("read x && [ \"$x\" = abcd ]", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - check_cloexec(fp, mode); - if (fputs("abcd\n", fp) == EOF) - fprintf(stderr, "Output error 1\n"), failures++; - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - fprintf(stderr, "Bad exit status (output)\n"), failures++; - } - - act.sa_handler = sigpipe_handler; - act.sa_flags = SA_RESTART; - sigemptyset(&act.sa_mask); - if (sigaction(SIGPIPE, &act, &oact) == -1) - fprintf(stderr, "sigaction() failed\n"), failures++; - for (i = 0; i < sizeof(wmodes) / sizeof(wmodes[0]); i++) { - mode = wmodes[i]; - fp = popen("exit 88", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - check_cloexec(fp, mode); - got_sigpipe = 0; - while (fputs("abcd\n", fp) != EOF) - ; - if (!ferror(fp) || errno != EPIPE) - fprintf(stderr, "Expected EPIPE\n"), failures++; - if (!got_sigpipe) - fprintf(stderr, "Expected SIGPIPE\n"), failures++; - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 88) - fprintf(stderr, "Bad exit status (EPIPE)\n"), failures++; - } - if (sigaction(SIGPIPE, &oact, NULL) == -1) - fprintf(stderr, "sigaction() failed\n"), failures++; - - for (i = 0; i < sizeof(rwmodes) / sizeof(rwmodes[0]); i++) { - mode = rwmodes[i]; - fp = popen("read x && printf '%s\\n' \"Q${x#a}\"", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - check_cloexec(fp, mode); - if (fputs("abcd\n", fp) == EOF) - fprintf(stderr, "Output error 2\n"), failures++; - if (fgets(buf, sizeof(buf), fp) == NULL) - fprintf(stderr, "Input error 3\n"), failures++; - else if (strcmp(buf, "Qbcd\n") != 0) - fprintf(stderr, "Bad input 2\n"), failures++; - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - fprintf(stderr, "Bad exit status (I/O)\n"), failures++; - } - - for (i = 0; i < sizeof(wmodes) / sizeof(wmodes[0]); i++) { - for (j = 0; j < sizeof(wmodes) / sizeof(wmodes[0]); j++) { - mode = wmodes[i]; - fp = popen("read x", mode); - if (fp == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - continue; - } - mode = wmodes[j]; - fp2 = popen("read x", mode); - if (fp2 == NULL) { - fprintf(stderr, "popen(, \"%s\") failed", mode); - failures++; - pclose(fp); - continue; - } - /* If fp2 inherits fp's pipe, we will deadlock here. */ - status = pclose(fp); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 1) { - fprintf(stderr, "Bad exit status (2 pipes)\n"); - failures++; - } - status = pclose(fp2); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 1) { - fprintf(stderr, "Bad exit status (2 pipes)\n"); - failures++; - } - } - } - - if (failures == 0) - printf("PASS popen()\n"); - - return (failures != 0); -} diff --git a/tools/regression/lib/libc/gen/test-wordexp.c b/tools/regression/lib/libc/gen/test-wordexp.c deleted file mode 100644 index 68b1578e4d04..000000000000 --- a/tools/regression/lib/libc/gen/test-wordexp.c +++ /dev/null @@ -1,271 +0,0 @@ -/*- - * 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 -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include -#include -#include - -static void -chld_handler(int x) -{ - int status, serrno; - - (void)x; - serrno = errno; - while (waitpid(-1, &status, WNOHANG) > 0) - ; - errno = serrno; -} - -int -main(int argc, char *argv[]) -{ - struct sigaction sa; - wordexp_t we; - int r; - int i; - char longdata[6 * 10000 + 1]; - - /* Test that the macros are there. */ - (void)(WRDE_APPEND + WRDE_DOOFFS + 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); - - /* Long output. */ - for (i = 0; i < 10000; i++) - snprintf(longdata + 6 * i, 7, "%05d ", i); - r = wordexp(longdata, &we, 0); - assert(r == 0); - assert(we.we_wordc == 10000); - assert(we.we_wordv[10000] == NULL); - wordfree(&we); - - /* WRDE_DOOFFS */ - we.we_offs = 3; - r = wordexp("hello world", &we, WRDE_DOOFFS); - 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_DOOFFS + WRDE_APPEND */ - we.we_offs = 2; - r = wordexp("this is", &we, WRDE_DOOFFS); - assert(r == 0); - r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFFS); - assert(r == 0); - r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFFS); - 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); - - /* WRDE_SYNTAX */ - r = wordexp("'", &we, 0); - assert(r == WRDE_SYNTAX); - r = wordexp("'", &we, WRDE_UNDEF); - assert(r == WRDE_SYNTAX); - r = wordexp("'\\'", &we, 0); - assert(r == 0); - assert(we.we_wordc == 1); - assert(strcmp(we.we_wordv[0], "\\") == 0); - assert(we.we_wordv[1] == NULL); - wordfree(&we); - /* Two syntax errors that are not detected by the current we_check(). */ - r = wordexp("${IFS:+'}", &we, 0); - assert(r == WRDE_SYNTAX); - r = wordexp("${IFS:+'}", &we, WRDE_UNDEF); - assert(r == WRDE_SYNTAX); - r = wordexp("$(case)", &we, 0); - assert(r == WRDE_SYNTAX); - r = wordexp("$(case)", &we, WRDE_UNDEF); - assert(r == WRDE_SYNTAX); - - /* With a SIGCHLD handler that reaps all zombies. */ - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = chld_handler; - r = sigaction(SIGCHLD, &sa, NULL); - assert(r == 0); - 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); - sa.sa_handler = SIG_DFL; - r = sigaction(SIGCHLD, &sa, NULL); - assert(r == 0); - - /* - * With IFS set to a non-default value (without depending on whether - * IFS is inherited or not). - */ - r = setenv("IFS", ":", 1); - assert(r == 0); - 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); - r = unsetenv("IFS"); - assert(r == 0); - - /* - * With IFS set to a non-default value, and using it. - */ - r = setenv("IFS", ":", 1); - assert(r == 0); - r = wordexp("${IFS+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); - r = unsetenv("IFS"); - assert(r == 0); - - printf("PASS wordexp()\n"); - printf("PASS wordfree()\n"); - - return (0); -}