OSDN Git Service

Implement unit tests for ANSI printf() functions.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Wed, 2 Nov 2016 17:03:51 +0000 (17:03 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Wed, 2 Nov 2016 17:03:51 +0000 (17:03 +0000)
mingwrt/ChangeLog
mingwrt/tests/Makefile.in
mingwrt/tests/ansiprintf.at [new file with mode: 0644]
mingwrt/tests/testsuite.at.in

index 751d0c0..520ed70 100644 (file)
@@ -1,3 +1,11 @@
+2016-11-02  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Implement unit tests for ANSI printf() functions.
+
+       * tests/Makefile.in (testsuite): Add dependency for...
+       * tests/ansiprintf.at: ...this new file, and...
+       * tests/testsuite.at.in: ...m4_include it.
+
 2016-11-01  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Fix another printf() hex-float formatting bug.
index 19ca799..dcae350 100644 (file)
@@ -99,9 +99,11 @@ AUTOTEST_COMPILE = $(autotest_@AUTOTEST_COMPILE@)
 autotest_command = autom4te --language autotest --include ${srcdir}
 autotest_missing = $(call missing,autom4te,Unable to compile the testsuite)
 
-testsuite: %: %.at headers.at
+testsuite: %: %.at
        $(AUTOTEST_COMPILE) -o $* $<
 
+testsuite: headers.at ansiprintf.at
+
 # Display a diagnostic message, explaining that any specified program
 # is required, but has not been installed.
 #
diff --git a/mingwrt/tests/ansiprintf.at b/mingwrt/tests/ansiprintf.at
new file mode 100644 (file)
index 0000000..65cbc30
--- /dev/null
@@ -0,0 +1,298 @@
+# ansiprintf.at
+#
+# Autotest module to verify correct operation of MinGW.org's suite of
+# ANSI compliant replacements for the printf() family of functions.
+#
+# $Id$
+#
+# Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+# Copyright (C) 2016, MinGW.org Project
+#
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+#
+# All tests specified herein are written in the C language.
+#
+MINGW_AT_LANG([C])
+
+# MINGW_AT_CHECK_PRINTF( FORMAT, ARGS, EXPOUT )
+# ---------------------------------------------
+# Set up the test case to evaluate the behaviour of printf() when
+# invoked with the specified (unquoted) FORMAT, and the given comma
+# separated list of ARGS; confirm that the resultant output matches
+# EXPOUT, (which is interpreted as CRLF delimited text).
+#
+m4_define([MINGW_AT_CHECK_PRINTF],[dnl
+AT_SETUP([printf ("$1", $2)])_MINGW_AT_CHECK_PRINTF([$1],[$2],[$3])dnl
+])m4_define([_MINGW_AT_CHECK_PRINTF],[dnl
+AT_KEYWORDS([C printf])
+MINGW_AT_DATA_CRLF([expout],[[$3
+]])MINGW_AT_CHECK_RUN([[[
+#define _XOPEN_SOURCE 700
+#include <stdio.h>
+#include <tgmath.h>
+int main()
+{ printf ("::]$1[::\n", ]$2[); return 0;
+}]]],,[expout])dnl
+AT_CLEANUP
+])# MINGW_AT_CHECK_PRINTF
+
+# MINGW_AT_XFAIL_PRINTF( FORMAT, ARGS, EXPOUT )
+# ---------------------------------------------
+# A variation on MINGW_AT_CHECK_PRINTF, used to introduce any test
+# from which the output is likely to differ from that which might be
+# expected for the given format and arguments, (e.g. the display of
+# numeric digits beyond the limit of precision for the data type).
+#
+m4_define([MINGW_AT_XFAIL_PRINTF],[dnl
+AT_SETUP([printf ("$1", $2)])AT_XFAIL_IF([true])dnl
+_MINGW_AT_CHECK_PRINTF([$1],[$2],[$3])dnl
+])# MINGW_AT_XFAIL_PRINTF
+
+
+# Test behaviour of "%d" format conversion, for decimal
+# display of integer values.
+#
+AT_BANNER([[ISO-C99 printf() integer value formatting.]])
+MINGW_AT_CHECK_PRINTF([[%20d]],    [+0],    [::                   0::])
+MINGW_AT_CHECK_PRINTF([[%+20d]],   [-0],    [::                  +0::])
+MINGW_AT_CHECK_PRINTF([[%020d]],   [+0],    [::00000000000000000000::])
+MINGW_AT_CHECK_PRINTF([[%-20d]],   [-0],    [::0                   ::])
+MINGW_AT_CHECK_PRINTF([[%20d]],    [+55],   [::                  55::])
+MINGW_AT_CHECK_PRINTF([[%20d]],    [-55],   [::                 -55::])
+MINGW_AT_CHECK_PRINTF([[%+20d]],   [+55],   [::                 +55::])
+MINGW_AT_CHECK_PRINTF([[%+20d]],   [-55],   [::                 -55::])
+MINGW_AT_CHECK_PRINTF([[%020d]],   [+55],   [::00000000000000000055::])
+MINGW_AT_CHECK_PRINTF([[%-20d]],   [+55],   [::55                  ::])
+
+
+# Test behaviour of "%#x" format conversion, for hexadecimal
+# display of integer values.
+#
+AT_BANNER([[ISO-C99 printf() hexadecimal integer formatting.]])
+MINGW_AT_CHECK_PRINTF([[%#20x]],   [-0],    [::                   0::])
+MINGW_AT_CHECK_PRINTF([[%#+20x]],  [+0],    [::                   0::])
+MINGW_AT_CHECK_PRINTF([[%#020x]],  [-0],    [::00000000000000000000::])
+MINGW_AT_CHECK_PRINTF([[%#-20x]],  [+0],    [::0                   ::])
+MINGW_AT_CHECK_PRINTF([[%#20x]],   [+77],   [::                0x4d::])
+MINGW_AT_CHECK_PRINTF([[%#20x]],   [-77],   [::          0xffffffb3::])
+MINGW_AT_CHECK_PRINTF([[%#+20x]],  [+77],   [::                0x4d::])
+MINGW_AT_CHECK_PRINTF([[%#+20x]],  [-77],   [::          0xffffffb3::])
+MINGW_AT_CHECK_PRINTF([[%#020x]],  [+77],   [::0x00000000000000004d::])
+MINGW_AT_CHECK_PRINTF([[%#-20x]],  [+77],   [::0x4d                ::])
+
+
+# Test effect of alignment and sign flags on "%f" format conversion.
+#
+AT_BANNER([[ISO-C99 printf() fixed point real number formatting.]])
+MINGW_AT_CHECK_PRINTF([[%20f]],    [M_E],   [::            2.718282::])
+MINGW_AT_CHECK_PRINTF([[% 20f]],   [M_E],   [::            2.718282::])
+MINGW_AT_CHECK_PRINTF([[%+20f]],   [M_E],   [::           +2.718282::])
+MINGW_AT_CHECK_PRINTF([[% 020f]],  [M_E],   [:: 000000000002.718282::])
+MINGW_AT_CHECK_PRINTF([[%020f]],   [M_E],   [::0000000000002.718282::])
+MINGW_AT_CHECK_PRINTF([[%+020f]],  [M_E],   [::+000000000002.718282::])
+MINGW_AT_CHECK_PRINTF([[%+ 020f]], [M_E],   [::+000000000002.718282::])
+MINGW_AT_CHECK_PRINTF([[%-20f]],   [M_E],   [::2.718282            ::])
+MINGW_AT_CHECK_PRINTF([[%- 20f]],  [M_E],   [:: 2.718282           ::])
+MINGW_AT_CHECK_PRINTF([[%-+20f]],  [M_E],   [::+2.718282           ::])
+MINGW_AT_CHECK_PRINTF([[%- +20f]], [M_E],   [::+2.718282           ::])
+MINGW_AT_CHECK_PRINTF([[%-020f]],  [M_E],   [::2.718282            ::])
+
+
+# Test the effect of "%f" format conversion, with a value which
+# requires in excess the representable 15-digit maximum precision
+# of the double data type; ideally, a value with an exact binary
+# representation would be displayed exactly, but we expect this
+# to fail, with garbage beyond the 15-digit boundary.
+#
+AT_BANNER([[ISO-C99 printf() fixed point formatting imprecision.]])
+MINGW_AT_XFAIL_PRINTF([[%30.1f]], [1e+26],  [:: 100000000000000000000000000.0::])
+
+
+# Test default behaviour of "%g" format conversion; (this should
+# have no non-significant trailing zeros, nor should it end with
+# a radix point without following non-zero fractional digits).
+#
+AT_BANNER([[ISO-C99 printf() floating point real number formatting.]])
+MINGW_AT_CHECK_PRINTF([[%20g]],  [1.75e+02], [::                 175::])
+MINGW_AT_CHECK_PRINTF([[%20g]],  [1.75e+05], [::              175000::])
+MINGW_AT_CHECK_PRINTF([[%20g]],  [1.75e+15], [::           1.75e+015::])
+MINGW_AT_CHECK_PRINTF([[%20g]],  [1.75e+00], [::                1.75::])
+MINGW_AT_CHECK_PRINTF([[%20g]],  [1.75e-03], [::             0.00175::])
+MINGW_AT_CHECK_PRINTF([[%20g]],  [1.75e-15], [::           1.75e-015::])
+
+
+# Test effect of alignment and sign flags on "%g" format conversion.
+#
+AT_BANNER([[ISO-C99 printf() floating point formatting with flags.]])
+MINGW_AT_CHECK_PRINTF([[%+20g]],   [M_E],    [::            +2.71828::])
+MINGW_AT_CHECK_PRINTF([[%020g]],   [M_E],    [::00000000000002.71828::])
+MINGW_AT_CHECK_PRINTF([[% 020g]],  [M_E],    [:: 0000000000002.71828::])
+MINGW_AT_CHECK_PRINTF([[%+020g]],  [M_E],    [::+0000000000002.71828::])
+MINGW_AT_CHECK_PRINTF([[%+ 020g]], [M_E],    [::+0000000000002.71828::])
+MINGW_AT_CHECK_PRINTF([[%-20g]],   [M_E],    [::2.71828             ::])
+MINGW_AT_CHECK_PRINTF([[%- 20g]],  [M_E],    [:: 2.71828            ::])
+MINGW_AT_CHECK_PRINTF([[%-+20g]],  [M_E],    [::+2.71828            ::])
+MINGW_AT_CHECK_PRINTF([[%- +20g]], [M_E],    [::+2.71828            ::])
+MINGW_AT_CHECK_PRINTF([[%-020g]],  [M_E],    [::2.71828             ::])
+
+
+# Test effect of "#" flag on "%g" format conversion; (this should
+# override suppression of non-significant trailing zeros).
+#
+AT_BANNER([[ISO-C99 printf() alternative floating point formatting.]])
+MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+02], [::             175.000::])
+MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+05], [::             175000.::])
+MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+15], [::        1.75000e+015::])
+MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+00], [::             1.75000::])
+MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e-03], [::          0.00175000::])
+MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e-15], [::        1.75000e-015::])
+
+
+# Test transition between "%e" and "%f" style representations, for
+# default precision "%g" format conversion.
+#
+AT_BANNER([[ISO-C99 printf() floating point format style transitions.]])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-6], [::        2.71828e-006::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-5], [::        2.71828e-005::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-4], [::         0.000271828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-3], [::          0.00271828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-2], [::           0.0271828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-1], [::            0.271828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+0], [::             2.71828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+1], [::             27.1828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+2], [::             271.828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+3], [::             2718.28::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+4], [::             27182.8::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+5], [::              271828::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+6], [::        2.71828e+006::])
+MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+7], [::        2.71828e+007::])
+
+
+# Test the effect of varying precision, as specified by the "*" format
+# modifier, on "%g" format conversion; (-ve precision implies default;
+# zero or +ve specifies actual significant digits).
+#
+AT_BANNER([[ISO-C99 printf() variable precision floating point format.]])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [-2, M_E], [::             2.71828::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [-1, M_E], [::             2.71828::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+0, M_E], [::                   3::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+1, M_E], [::                   3::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+2, M_E], [::                 2.7::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+3, M_E], [::                2.72::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+4, M_E], [::               2.718::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+5, M_E], [::              2.7183::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+6, M_E], [::             2.71828::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+7, M_E], [::            2.718282::])
+MINGW_AT_CHECK_PRINTF([[%20.*g]], [+8, M_E], [::           2.7182818::])
+
+
+# Test variations of "%e" format conversion.
+#
+AT_BANNER([[ISO-C99 printf() scientific style floating point format.]])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [+M_E * 0.0], [::      0.0000000e+000::])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [-M_E * 0.0], [::     -0.0000000e+000::])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [+M_E * 1.0], [::      2.7182818e+000::])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [-M_E * 1.0], [::     -2.7182818e+000::])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [+M_E / 0.0], [::                 inf::])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [-M_E / 0.0], [::                -inf::])
+MINGW_AT_CHECK_PRINTF([[%20.7e]],  [-0.0 / 0.0], [::                 nan::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [+M_E * 0.0], [::0.0000000e+000      ::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-M_E * 0.0], [::-0.0000000e+000     ::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [+M_E * 1.0], [::2.7182818e+000      ::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-M_E * 1.0], [::-2.7182818e+000     ::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [+M_E / 0.0], [::inf                 ::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-M_E / 0.0], [::-inf                ::])
+MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-0.0 / 0.0], [::nan                 ::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [+M_E * 0.0], [::     +0.0000000e+000::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-M_E * 0.0], [::     -0.0000000e+000::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [+M_E * 1.0], [::     +2.7182818e+000::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-M_E * 1.0], [::     -2.7182818e+000::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [+M_E / 0.0], [::                +inf::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-M_E / 0.0], [::                -inf::])
+MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-0.0 / 0.0], [::                +nan::])
+
+
+# Test variations of "%a" format conversion; (the following integer
+# value confirms correct size of the floating point entity passed on
+# the printf() argument stack).
+#
+AT_BANNER([[ISO-C99 printf() hexadecimal floating point formatting.]])
+MINGW_AT_CHECK_PRINTF([[%16a%4d]],    [0.000, 77],  [::          0x0p+0  77::])
+MINGW_AT_CHECK_PRINTF([[%16.3a%4d]],  [0.000, 99],  [::      0x0.000p+0  99::])
+MINGW_AT_CHECK_PRINTF([[%16a%4d]],    [1.750, 77],  [::          0xep-3  77::])
+MINGW_AT_CHECK_PRINTF([[%016a%4d]],   [1.750, 77],  [::0x0000000000ep-3  77::])
+MINGW_AT_CHECK_PRINTF([[%-016a%4d]],  [1.750, 77],  [::0xep-3            77::])
+MINGW_AT_CHECK_PRINTF([[%16.0a%4d]],  [1.450, 44],  [::          0xcp-3  44::])
+MINGW_AT_CHECK_PRINTF([[%16.1a%4d]],  [1.999, 99],  [::        0x8.0p-2  99::])
+MINGW_AT_CHECK_PRINTF([[%16La%4d]],   [1.750L, 77], [::          0xep-3  77::])
+MINGW_AT_CHECK_PRINTF([[%016La%4d]],  [1.750L, 77], [::0x0000000000ep-3  77::])
+MINGW_AT_CHECK_PRINTF([[%16.0La%4d]], [1.450L, 44], [::          0xcp-3  44::])
+MINGW_AT_CHECK_PRINTF([[%16.1La%4d]], [1.999L, 99], [::        0x8.0p-2  99::])
+
+
+# MINGW_AT_CHECK_SNPRINTF( FORMAT, MAXCOUNT, INITCOUNT )
+# ------------------------------------------------------
+# Test the behaviour of the snprintf() function, with respect to
+# output truncation at specified MAXCOUNT (no more than 32), when
+# writing string "Sample text; sufficient buffer" subject to the
+# specified.  Also supports testing the effect of "%n" counting
+# on an internal integer variable, initialized to INITCOUNT.
+#
+m4_define([MINGW_AT_CHECK_SNPRINTF],[dnl
+AT_SETUP([snprintf (output, $2, "$1", ...)])
+AT_KEYWORDS([C printf])MINGW_AT_DATA_CRLF([expout],[[$4
+]])MINGW_AT_CHECK_RUN([[[
+#define _XOPEN_SOURCE 700
+#include <stdio.h>
+int main()
+{ char output[32]; int capture = ]$3[;
+  const char *sample = "Sample text; sufficient buffer";
+  int total = snprintf (output, ]$2[, "]$1[", sample, &capture);
+  snprintf (NULL, 0, "]$1[", output, &capture);
+  printf ("%s: %d required; %d captured\n", output, total, capture);
+  return 0;
+}]]],,[expout])dnl
+AT_CLEANUP
+])# MINGW_AT_CHECK_SNPRINTF
+
+
+# Tests for snprintf() with limited length internal buffer.
+#
+AT_BANNER([ISO-C99 snprintf() buffer length control.])
+MINGW_AT_CHECK_SNPRINTF([[%s]],[32],[1024],dnl
+[Sample text; sufficient buffer: 30 required; 1024 captured])
+MINGW_AT_CHECK_SNPRINTF([[%s]],[12],[1024],dnl
+[Sample text: 30 required; 1024 captured])
+
+
+# Tests for effect of "%n" output length counting.
+#
+AT_BANNER([ISO-C99 snprintf() intermediate output counting.])
+MINGW_AT_CHECK_SNPRINTF([[%s%n]],[32],[1024],dnl
+[Sample text; sufficient buffer: 30 required; 30 captured])
+MINGW_AT_CHECK_SNPRINTF([[%s%n]],[12],[1024],dnl
+[Sample text: 30 required; 11 captured])
+MINGW_AT_CHECK_SNPRINTF([[%s%hhn]],[12],[1024],dnl
+[Sample text: 30 required; 1035 captured])
+
+# vim: filetype=config formatoptions=croql
+# $RCSfile$: end of file
index 527b21d..3e565e4 100644 (file)
@@ -87,6 +87,7 @@ MINGW_AT_LANG([C])
 # collection of autotest M4 include files.
 #
 m4_include([headers.at])
+m4_include([ansiprintf.at])
 
 # vim: filetype=config formatoptions=croql
 # $RCSfile$: end of file