2011-05-20 Eric Blake <eblake@redhat.com>
+ test-perror: check for strerror interactions
+ * tests/macros.h (STREQ) Add macro.
+ * modules/perror-tests (Files): Add second test.
+ * tests/test-perror2.c (main): New file.
+ * doc/posix-functions/perror.texi (perror): Document glibc bug.
+
test-perror: rewrite to use init script
* modules/perror-tests (Files): Add init.sh.
* tests/test-perror.sh: Use temporary directory.
--- /dev/null
+/* Test of perror() function.
+ Copyright (C) 2011 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, 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, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+/* This test intentionally parses stderr. So, we arrange to have fd 10
+ (outside the range of interesting fd's during the test) set up to
+ duplicate the original stderr. */
+#define BACKUP_STDERR_FILENO 10
+#define ASSERT_STREAM myerr
+#include "macros.h"
+
+static FILE *myerr;
+
+#define BASE "test-perror2"
+
+int
+main (void)
+{
+ FILE *fp;
+
+ /* We change fd 2 later, so save it in fd 10. */
+ if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
+ || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
+ return 2;
+
+ ASSERT (freopen (BASE ".tmp", "w+", stderr) == stderr);
+
+ /* Test that perror does not clobber strerror buffer. */
+ {
+ const char *msg1;
+ const char *msg2;
+ const char *msg3;
+ const char *msg4;
+ char *str1;
+ char *str2;
+ char *str3;
+ char *str4;
+
+ msg1 = strerror (ENOENT);
+ ASSERT (msg1);
+ str1 = strdup (msg1);
+ ASSERT (str1);
+
+ msg2 = strerror (ERANGE);
+ ASSERT (msg2);
+ str2 = strdup (msg2);
+ ASSERT (str2);
+
+ msg3 = strerror (-4);
+ ASSERT (msg3);
+ str3 = strdup (msg3);
+ ASSERT (str3);
+
+ msg4 = strerror (1729576);
+ ASSERT (msg4);
+ str4 = strdup (msg4);
+ ASSERT (str4);
+
+ errno = EACCES;
+ perror ("");
+ errno = -5;
+ perror ("");
+ ASSERT (!ferror (stderr));
+ ASSERT (msg1 == msg2 || msg1 == msg4 || STREQ (msg1, str1));
+ ASSERT (msg2 == msg4 || STREQ (msg2, str2));
+ ASSERT (msg3 == msg4 || STREQ (msg3, str3));
+ ASSERT (STREQ (msg4, str4));
+ }
+
+ /* Test that perror reports write failure. */
+ {
+ ASSERT (freopen (BASE ".tmp", "r", stderr) == stderr);
+ ASSERT (setvbuf (stderr, NULL, _IOLBF, BUFSIZ) == 0);
+ errno = -1;
+ ASSERT (!ferror (stderr));
+ perror (NULL);
+ ASSERT (errno > 0);
+#if 0
+ /* Commented out until glibc behaves:
+ http://sourceware.org/bugzilla/show_bug.cgi?id=12792 */
+ ASSERT (ferror (stderr));
+#endif
+ }
+
+ ASSERT (fclose (stderr) == 0);
+ ASSERT (remove (BASE ".tmp") == 0);
+
+ return 0;
+}