diff options
Diffstat (limited to 'tests/test-errno-h.c')
-rw-r--r-- | tests/test-errno-h.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/tests/test-errno-h.c b/tests/test-errno-h.c new file mode 100644 index 00000000..cb20635b --- /dev/null +++ b/tests/test-errno-h.c @@ -0,0 +1,166 @@ +/* Test of <errno.h> substitute. + Copyright (C) 2008-2025 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2008. */ + +#include <config.h> + +#include <errno.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Check all POSIX-defined errno values, using M (v) to check value v. */ +#define CHECK_POSIX_ERRNOS(m) \ + m (E2BIG) \ + m (EACCES) \ + m (EADDRINUSE) \ + m (EADDRNOTAVAIL) \ + m (EAFNOSUPPORT) \ + m (EAGAIN) \ + m (EALREADY) \ + m (EBADF) \ + m (EBADMSG) \ + m (EBUSY) \ + m (ECANCELED) \ + m (ECHILD) \ + m (ECONNABORTED) \ + m (ECONNREFUSED) \ + m (ECONNRESET) \ + m (EDEADLK) \ + m (EDESTADDRREQ) \ + m (EDOM) \ + m (EDQUOT) \ + m (EEXIST) \ + m (EFAULT) \ + m (EFBIG) \ + m (EHOSTUNREACH) \ + m (EIDRM) \ + m (EILSEQ) \ + m (EINPROGRESS) \ + m (EINTR) \ + m (EINVAL) \ + m (EIO) \ + m (EISCONN) \ + m (EISDIR) \ + m (ELOOP) \ + m (EMFILE) \ + m (EMLINK) \ + m (EMSGSIZE) \ + m (EMULTIHOP) \ + m (ENAMETOOLONG) \ + m (ENETDOWN) \ + m (ENETRESET) \ + m (ENETUNREACH) \ + m (ENFILE) \ + m (ENOBUFS) \ + m (ENODEV) \ + m (ENOENT) \ + m (ENOEXEC) \ + m (ENOLCK) \ + m (ENOLINK) \ + m (ENOMEM) \ + m (ENOMSG) \ + m (ENOPROTOOPT) \ + m (ENOSPC) \ + m (ENOSYS) \ + m (ENOTCONN) \ + m (ENOTDIR) \ + m (ENOTEMPTY) \ + m (ENOTRECOVERABLE) \ + m (ENOTSOCK) \ + m (ENOTSUP) \ + m (ENOTTY) \ + m (ENXIO) \ + m (EOPNOTSUPP) \ + m (EOVERFLOW) \ + m (EOWNERDEAD) \ + m (EPERM) \ + m (EPIPE) \ + m (EPROTO) \ + m (EPROTONOSUPPORT) \ + m (EPROTOTYPE) \ + m (ERANGE) \ + m (EROFS) \ + m (ESOCKTNOSUPPORT) \ + m (ESPIPE) \ + m (ESRCH) \ + m (ESTALE) \ + m (ETIMEDOUT) \ + m (ETXTBSY) \ + m (EWOULDBLOCK) \ + m (EXDEV) \ + /* end of CHECK_POSIX_ERRNOS */ + +/* Verify that the POSIX mandated errno values can be used as integer + constant expressions and are all positive (except on Haiku). */ +#if defined __HAIKU__ +# define NONZERO_INTEGER_CONSTANT_EXPRESSION(e) static_assert (0 != (e) << 0); +CHECK_POSIX_ERRNOS (NONZERO_INTEGER_CONSTANT_EXPRESSION) +#else +# define POSITIVE_INTEGER_CONSTANT_EXPRESSION(e) static_assert (0 < (e) << 0); +CHECK_POSIX_ERRNOS (POSITIVE_INTEGER_CONSTANT_EXPRESSION) +#endif + +/* Verify that errno values can all be used in #if. */ +#define USABLE_IN_IF(e) ^ e +#if 0 CHECK_POSIX_ERRNOS (USABLE_IN_IF) +#endif + +/* Check that errno values all differ, except possibly for + EWOULDBLOCK == EAGAIN and ENOTSUP == EOPNOTSUPP. */ +#define ERRTAB(e) { #e, e }, +static struct nameval { char const *name; int value; } + errtab[] = { CHECK_POSIX_ERRNOS (ERRTAB) }; + +static int +errtab_cmp (void const *va, void const *vb) +{ + struct nameval const *a = va, *b = vb; + + /* Sort by value first, then by name (to simplify later tests). + Subtraction cannot overflow as both are positive. */ + int diff = a->value - b->value; + return diff ? diff : strcmp (a->name, b->name); +} + +int +main () +{ + int test_exit_status = EXIT_SUCCESS; + + /* Verify that errno can be assigned. */ + errno = EOVERFLOW; + + /* Check that errno values all differ, except possibly for + EAGAIN == EWOULDBLOCK and ENOTSUP == EOPNOTSUPP. */ + int nerrtab = sizeof errtab / sizeof *errtab; + qsort (errtab, nerrtab, sizeof *errtab, errtab_cmp); + for (int i = 1; i < nerrtab; i++) + if (errtab[i - 1].value == errtab[i].value) + { + fprintf (stderr, "%s == %s == %d\n", + errtab[i - 1].name, errtab[i].name, errtab[i].value); + if (! ((strcmp ("EAGAIN", errtab[i - 1].name) == 0 + && strcmp ("EWOULDBLOCK", errtab[i].name) == 0) + || (strcmp ("ENOTSUP", errtab[i - 1].name) == 0 + && strcmp ("EOPNOTSUPP", errtab[i].name) == 0))) + test_exit_status = EXIT_FAILURE; + } + + return test_exit_status; +} |