changeset 9443:1df2e8a2fa66

New tests for modules 'test-fprintf-posix' and 'test-printf-posix'.
author Bruno Haible <bruno@clisp.org>
date Sat, 03 Nov 2007 17:00:19 +0100
parents ad275322f8f1
children 0c3b25464595
files ChangeLog modules/fprintf-posix-tests modules/printf-posix-tests tests/test-fprintf-posix2.c tests/test-fprintf-posix2.sh tests/test-printf-posix2.c tests/test-printf-posix2.sh
diffstat 7 files changed, 357 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+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.
--- a/modules/fprintf-posix-tests
+++ b/modules/fprintf-posix-tests
@@ -3,13 +3,16 @@
 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
--- a/modules/printf-posix-tests
+++ b/modules/printf-posix-tests
@@ -3,13 +3,16 @@
 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
new file mode 100644
--- /dev/null
+++ b/tests/test-fprintf-posix2.c
@@ -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
new file mode 100755
--- /dev/null
+++ b/tests/test-fprintf-posix2.sh
@@ -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
new file mode 100644
--- /dev/null
+++ b/tests/test-printf-posix2.c
@@ -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
new file mode 100755
--- /dev/null
+++ b/tests/test-printf-posix2.sh
@@ -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