New tests for modules 'test-fprintf-posix' and 'test-printf-posix'.
authorBruno Haible <bruno@clisp.org>
Sat, 3 Nov 2007 16:00:19 +0000 (17:00 +0100)
committerBruno Haible <bruno@clisp.org>
Sat, 3 Nov 2007 16:00:19 +0000 (17:00 +0100)
ChangeLog
modules/fprintf-posix-tests
modules/printf-posix-tests
tests/test-fprintf-posix2.c [new file with mode: 0644]
tests/test-fprintf-posix2.sh [new file with mode: 0755]
tests/test-printf-posix2.c [new file with mode: 0644]
tests/test-printf-posix2.sh [new file with mode: 0755]

index ede86dd..e976094 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,60 @@
 2007-11-03  Bruno Haible  <bruno@clisp.org>
 
+       * tests/test-fprintf-posix2.sh: New file.
+       * tests/test-fprintf-posix2.c: New file.
+       * modules/fprintf-posix-tests (Files): Add them.
+       (TESTS): Add test-fprintf-posix2.sh.
+       (configure.ac): Check for getrlimit and setrlimit.
+       (check_PROGRAMS): Add test-fprintf-posix2.
+
+       * tests/test-printf-posix2.sh: New file.
+       * tests/test-printf-posix2.c: New file.
+       * modules/printf-posix-tests (Files): Add them.
+       (TESTS): Add test-printf-posix2.sh.
+       (configure.ac): Check for getrlimit and setrlimit.
+       (check_PROGRAMS): Add test-printf-posix2.
+
+       Fix *printf behaviour in out-of-memory situations on MacOS X and *BSD.
+       * m4/printf.m4 (gl_PRINTF_ENOMEM): New macro.
+       * lib/vasnprintf.c: Implement NEED_PRINTF_DOUBLE.
+       (decode_double): New function, copied from decode_long_double.
+       (scale10_round_decimal_decoded): New function, extracted from
+       scale10_round_decimal_long_double.
+       (scale10_round_decimal_long_double): Use it.
+       (scale10_round_decimal_double): New function.
+       (floorlog10): New function.
+       (VASNPRINTF): Handle NEED_PRINTF_DOUBLE case.
+       * m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_ENOMEM): New macro.
+       (gl_PREREQ_VASNPRINTF_WITH_EXTRAS): Invoke it.
+       * m4/fprintf-posix.m4 (gl_FUNC_FPRINTF_POSIX): Invoke
+       gl_PRINTF_ENOMEM and test its result. Invoke
+       gl_PREREQ_VASNPRINTF_ENOMEM.
+       * m4/snprintf-posix.m4 (gl_FUNC_SNPRINTF_POSIX): Likewise.
+       * m4/sprintf-posix.m4 (gl_FUNC_SPRINTF_POSIX): Likewise.
+       * m4/vasnprintf-posix.m4 (gl_FUNC_VASNPRINTF_POSIX): Likewise.
+       * m4/vasprintf-posix.m4 (gl_FUNC_VASPRINTF_POSIX): Likewise.
+       * m4/vfprintf-posix.m4 (gl_FUNC_VFPRINTF_POSIX): Likewise.
+       * m4/vsnprintf-posix.m4 (gl_FUNC_VSNPRINTF_POSIX): Likewise.
+       * m4/vsprintf-posix.m4 (gl_FUNC_VSPRINTF_POSIX): Likewise.
+       * modules/fprintf-posix (Depends-on): Add frexp-nolibm.
+       * modules/snprintf-posix (Depends-on): Likewise.
+       * modules/sprintf-posix (Depends-on): Likewise.
+       * modules/vasnprintf-posix (Depends-on): Likewise.
+       * modules/vasprintf-posix (Depends-on): Likewise.
+       * modules/vfprintf-posix (Depends-on): Likewise.
+       * modules/vsnprintf-posix (Depends-on): Likewise.
+       * modules/vsprintf-posix (Depends-on): Likewise.
+       * doc/functions/fprintf.texi: Update.
+       * doc/functions/printf.texi: Update.
+       * doc/functions/snprintf.texi: Update.
+       * doc/functions/sprintf.texi: Update.
+       * doc/functions/vfprintf.texi: Update.
+       * doc/functions/vprintf.texi: Update.
+       * doc/functions/vsnprintf.texi: Update.
+       * doc/functions/vsprintf.texi: Update.
+
+2007-11-03  Bruno Haible  <bruno@clisp.org>
+
        * modules/frexp-nolibm-tests: New file.
 
        * modules/frexp-nolibm: New file.
index 6d87969..b3fdea7 100644 (file)
@@ -3,13 +3,16 @@ tests/test-fprintf-posix.sh
 tests/test-fprintf-posix.c
 tests/test-fprintf-posix.h
 tests/test-printf-posix.output
+tests/test-fprintf-posix2.sh
+tests/test-fprintf-posix2.c
 
 Depends-on:
 stdint
 
 configure.ac:
+AC_CHECK_FUNCS_ONCE([getrlimit setrlimit])
 
 Makefile.am:
-TESTS += test-fprintf-posix.sh
+TESTS += test-fprintf-posix.sh test-fprintf-posix2.sh
 TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'
-check_PROGRAMS += test-fprintf-posix
+check_PROGRAMS += test-fprintf-posix test-fprintf-posix2
index 8d4157f..30ced62 100644 (file)
@@ -3,13 +3,16 @@ tests/test-printf-posix.sh
 tests/test-printf-posix.c
 tests/test-printf-posix.h
 tests/test-printf-posix.output
+tests/test-printf-posix2.sh
+tests/test-printf-posix2.c
 
 Depends-on:
 stdint
 
 configure.ac:
+AC_CHECK_FUNCS_ONCE([getrlimit setrlimit])
 
 Makefile.am:
-TESTS += test-printf-posix.sh
+TESTS += test-printf-posix.sh test-printf-posix2.sh
 TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'
-check_PROGRAMS += test-printf-posix
+check_PROGRAMS += test-printf-posix test-printf-posix2
diff --git a/tests/test-fprintf-posix2.c b/tests/test-fprintf-posix2.c
new file mode 100644 (file)
index 0000000..6d6dc08
--- /dev/null
@@ -0,0 +1,112 @@
+/* Test of POSIX compatible fprintf() function.
+   Copyright (C) 2007 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 <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#if HAVE_GETRLIMIT && HAVE_SETRLIMIT
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <errno.h>
+
+int
+main (int argc, char *argv[])
+{
+  struct rlimit limit;
+  int arg;
+  int ret;
+
+  /* Some printf implementations allocate temporary space with malloc.  */
+  /* On BSD systems, malloc() is limited by RLIMIT_DATA.  */
+#ifdef RLIMIT_DATA
+  if (getrlimit (RLIMIT_DATA, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_DATA, &limit) < 0)
+    return 77;
+#endif
+  /* On Linux systems, malloc() is limited by RLIMIT_AS.  */
+#ifdef RLIMIT_AS
+  if (getrlimit (RLIMIT_AS, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_AS, &limit) < 0)
+    return 77;
+#endif
+  /* Some printf implementations allocate temporary space on the stack.  */
+#ifdef RLIMIT_STACK
+  if (getrlimit (RLIMIT_STACK, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_STACK, &limit) < 0)
+    return 77;
+#endif
+
+  arg = atoi (argv[1]);
+  switch (arg)
+    {
+    case 0:
+      {
+       void *memory = malloc (5000000);
+       if (memory == NULL)
+         return 1;
+       memset (memory, 17, 5000000);
+       return 78;
+      }
+    case 1:
+      ret = fprintf (stdout, "%.5000000f", 1.0);
+      return !(ret == 5000002 || (ret < 0 && errno == ENOMEM));
+    case 2:
+      ret = fprintf (stdout, "%.5000000f", -1.0);
+      return !(ret == 5000003 || (ret < 0 && errno == ENOMEM));
+    case 3:
+      ret = fprintf (stdout, "%.5000000e", 1.0);
+      return !(ret >= 5000006 || (ret < 0 && errno == ENOMEM));
+    case 4:
+      ret = fprintf (stdout, "%.5000000d", 1);
+      return !(ret == 5000000 || (ret < 0 && errno == ENOMEM));
+    case 5:
+      ret = fprintf (stdout, "%.5000000d", -1);
+      return !(ret == 5000001 || (ret < 0 && errno == ENOMEM));
+    case 6:
+      ret = fprintf (stdout, "%.5000000u", 1);
+      return !(ret == 5000000 || (ret < 0 && errno == ENOMEM));
+    }
+  return 0;
+}
+
+#else
+
+int
+main (int argc, char *argv[])
+{
+  return 77;
+}
+
+#endif
diff --git a/tests/test-fprintf-posix2.sh b/tests/test-fprintf-posix2.sh
new file mode 100755 (executable)
index 0000000..79d92af
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Test out-of-memory handling.
+
+(./test-fprintf-posix2${EXEEXT} 0
+ result=$?
+ if test $result != 77 && test $result != 78; then result=1; fi
+ exit $result
+) 2>/dev/null
+malloc_result=$?
+if test $malloc_result = 77; then
+  echo "Skipping test: getrlimit and setrlimit don't work"
+  exit 77
+fi
+
+for arg in 1 2 3 4 5 6
+do
+  ./test-fprintf-posix2${EXEEXT} $arg > /dev/null
+  result=$?
+  if test $result = 77; then
+    echo "Skipping test: getrlimit and setrlimit don't work"
+    exit 77
+  fi
+  if test $result != 0; then
+    exit 1
+  fi
+done
+
+if test $malloc_result = 78; then
+  echo "Skipping test: getrlimit and setrlimit don't work"
+  exit 77
+fi
+
+exit 0
diff --git a/tests/test-printf-posix2.c b/tests/test-printf-posix2.c
new file mode 100644 (file)
index 0000000..b6e4fcc
--- /dev/null
@@ -0,0 +1,112 @@
+/* Test of POSIX compatible printf() function.
+   Copyright (C) 2007 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 <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#if HAVE_GETRLIMIT && HAVE_SETRLIMIT
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <errno.h>
+
+int
+main (int argc, char *argv[])
+{
+  struct rlimit limit;
+  int arg;
+  int ret;
+
+  /* Some printf implementations allocate temporary space with malloc.  */
+  /* On BSD systems, malloc() is limited by RLIMIT_DATA.  */
+#ifdef RLIMIT_DATA
+  if (getrlimit (RLIMIT_DATA, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_DATA, &limit) < 0)
+    return 77;
+#endif
+  /* On Linux systems, malloc() is limited by RLIMIT_AS.  */
+#ifdef RLIMIT_AS
+  if (getrlimit (RLIMIT_AS, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_AS, &limit) < 0)
+    return 77;
+#endif
+  /* Some printf implementations allocate temporary space on the stack.  */
+#ifdef RLIMIT_STACK
+  if (getrlimit (RLIMIT_STACK, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_STACK, &limit) < 0)
+    return 77;
+#endif
+
+  arg = atoi (argv[1]);
+  switch (arg)
+    {
+    case 0:
+      {
+       void *memory = malloc (5000000);
+       if (memory == NULL)
+         return 1;
+       memset (memory, 17, 5000000);
+       return 78;
+      }
+    case 1:
+      ret = printf ("%.5000000f", 1.0);
+      return !(ret == 5000002 || (ret < 0 && errno == ENOMEM));
+    case 2:
+      ret = printf ("%.5000000f", -1.0);
+      return !(ret == 5000003 || (ret < 0 && errno == ENOMEM));
+    case 3:
+      ret = printf ("%.5000000e", 1.0);
+      return !(ret >= 5000006 || (ret < 0 && errno == ENOMEM));
+    case 4:
+      ret = printf ("%.5000000d", 1);
+      return !(ret == 5000000 || (ret < 0 && errno == ENOMEM));
+    case 5:
+      ret = printf ("%.5000000d", -1);
+      return !(ret == 5000001 || (ret < 0 && errno == ENOMEM));
+    case 6:
+      ret = printf ("%.5000000u", 1);
+      return !(ret == 5000000 || (ret < 0 && errno == ENOMEM));
+    }
+  return 0;
+}
+
+#else
+
+int
+main (int argc, char *argv[])
+{
+  return 77;
+}
+
+#endif
diff --git a/tests/test-printf-posix2.sh b/tests/test-printf-posix2.sh
new file mode 100755 (executable)
index 0000000..893c3c9
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Test out-of-memory handling.
+
+(./test-printf-posix2${EXEEXT} 0
+ result=$?
+ if test $result != 77 && test $result != 78; then result=1; fi
+ exit $result
+) 2>/dev/null
+malloc_result=$?
+if test $malloc_result = 77; then
+  echo "Skipping test: getrlimit and setrlimit don't work"
+  exit 77
+fi
+
+for arg in 1 2 3 4 5 6
+do
+  ./test-printf-posix2${EXEEXT} $arg > /dev/null
+  result=$?
+  if test $result = 77; then
+    echo "Skipping test: getrlimit and setrlimit don't work"
+    exit 77
+  fi
+  if test $result != 0; then
+    exit 1
+  fi
+done
+
+if test $malloc_result = 78; then
+  echo "Skipping test: getrlimit and setrlimit don't work"
+  exit 77
+fi
+
+exit 0