Module Name: src
Committed By: kre
Date: Wed Sep 5 21:05:40 UTC 2018
Modified Files:
src/distrib/sets/lists/tests: mi
src/etc/mtree: NetBSD.dist.tests
src/tests/usr.bin: Makefile
Added Files:
src/tests/usr.bin/printf: Makefile printf.sh t_builtin.sh t_command.sh
Log Message:
Add ATF tests for printf(1)
Two new test programs, one for the version of printf in /bin/sh
and one for the command /usr/bin/printf (t_builtin and t_command)
Each test program has 28 test cases (the same in each) of which
currently 27 pass, and 1 is skipped.
See the test scripts themselves for more information.
To generate a diff of this commit:
cvs rdiff -u -r1.793 -r1.794 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.152 -r1.153 src/etc/mtree/NetBSD.dist.tests
cvs rdiff -u -r1.25 -r1.26 src/tests/usr.bin/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/printf/Makefile \
src/tests/usr.bin/printf/printf.sh src/tests/usr.bin/printf/t_builtin.sh \
src/tests/usr.bin/printf/t_command.sh
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.793 src/distrib/sets/lists/tests/mi:1.794
--- src/distrib/sets/lists/tests/mi:1.793 Tue Aug 21 11:07:40 2018
+++ src/distrib/sets/lists/tests/mi Wed Sep 5 21:05:40 2018
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.793 2018/08/21 11:07:40 christos Exp $
+# $NetBSD: mi,v 1.794 2018/09/05 21:05:40 kre Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -3945,6 +3945,11 @@
./usr/tests/usr.bin/pr/d_basic.in tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/pr/d_basic.out tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/pr/t_basic tests-usr.bin-tests compattestfile,atf
+./usr/tests/usr.bin/printf tests-usr.bin-tests compattestfile,atf
+./usr/tests/usr.bin/printf/Atffile tests-usr.bin-tests compattestfile,atf
+./usr/tests/usr.bin/printf/Kyuafile tests-usr.bin-tests compattestfile,atf,kyua
+./usr/tests/usr.bin/printf/t_builtin tests-usr.bin-tests compattestfile,atf
+./usr/tests/usr.bin/printf/t_command tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/rump_server tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/rump_server/Atffile tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/rump_server/Kyuafile tests-usr.bin-tests compattestfile,atf,kyua
Index: src/etc/mtree/NetBSD.dist.tests
diff -u src/etc/mtree/NetBSD.dist.tests:1.152 src/etc/mtree/NetBSD.dist.tests:1.153
--- src/etc/mtree/NetBSD.dist.tests:1.152 Fri Aug 3 04:24:41 2018
+++ src/etc/mtree/NetBSD.dist.tests Wed Sep 5 21:05:40 2018
@@ -1,4 +1,4 @@
-# $NetBSD: NetBSD.dist.tests,v 1.152 2018/08/03 04:24:41 kamil Exp $
+# $NetBSD: NetBSD.dist.tests,v 1.153 2018/09/05 21:05:40 kre Exp $
./usr/libdata/debug/usr/tests
./usr/libdata/debug/usr/tests/atf
@@ -410,6 +410,7 @@
./usr/tests/usr.bin/nbperf
./usr/tests/usr.bin/pkill
./usr/tests/usr.bin/pr
+./usr/tests/usr.bin/printf
./usr/tests/usr.bin/rump_server
./usr/tests/usr.bin/sdiff
./usr/tests/usr.bin/sed
Index: src/tests/usr.bin/Makefile
diff -u src/tests/usr.bin/Makefile:1.25 src/tests/usr.bin/Makefile:1.26
--- src/tests/usr.bin/Makefile:1.25 Sun May 14 00:07:07 2017
+++ src/tests/usr.bin/Makefile Wed Sep 5 21:05:40 2018
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.25 2017/05/14 00:07:07 kamil Exp $
+# $NetBSD: Makefile,v 1.26 2018/09/05 21:05:40 kre Exp $
#
.include <bsd.own.mk>
@@ -8,7 +8,7 @@ TESTSDIR= ${TESTSBASE}/usr.bin
TESTS_SUBDIRS= awk basename bzip2 cc cmp config cut \
diff dirname find gdb grep gzip id \
infocmp jot ld m4 make mixerctl mkdep nbperf netpgpverify \
- pkill pr rump_server shmif_dumpbus sdiff \
+ pkill pr printf rump_server shmif_dumpbus sdiff \
sed sort tmux tr unifdef uniq vmstat xlint
.if ${MKCXX} != "no"
Added files:
Index: src/tests/usr.bin/printf/Makefile
diff -u /dev/null src/tests/usr.bin/printf/Makefile:1.1
--- /dev/null Wed Sep 5 21:05:40 2018
+++ src/tests/usr.bin/printf/Makefile Wed Sep 5 21:05:40 2018
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile,v 1.1 2018/09/05 21:05:40 kre Exp $
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/printf
+
+TESTS_SH= t_builtin t_command
+
+t_builtin: t_builtin.sh printf.sh
+
+t_command: t_command.sh printf.sh
+
+.include <bsd.test.mk>
Index: src/tests/usr.bin/printf/printf.sh
diff -u /dev/null src/tests/usr.bin/printf/printf.sh:1.1
--- /dev/null Wed Sep 5 21:05:40 2018
+++ src/tests/usr.bin/printf/printf.sh Wed Sep 5 21:05:40 2018
@@ -0,0 +1,1781 @@
+# $NetBSD: printf.sh,v 1.1 2018/09/05 21:05:40 kre Exp $
+#
+# Copyright (c) 2018 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+Running_under_ATF=false
+test -n "${Atf_Shell}" && test -n "${Atf_Check}" && Running_under_ATF=true
+
+Tests=
+
+# create a test case:
+# "$1" is basic test name, "$2" is description
+define()
+{
+ NAME=$1; shift
+
+ if $Running_under_ATF
+ then
+ eval "${NAME}_head() { set descr 'Tests printf: $*'; }"
+ eval "${NAME}_body() { ${NAME} ; }"
+ else
+ eval "TEST_${NAME}_MSG="'"$*"'
+ fi
+
+ Tests="${Tests} ${NAME}"
+}
+
+
+# 1st arg is printf format conversion specifier
+# other args (if any) are args to that format
+# returns success if that conversion specifier is supported, false otherwise
+supported()
+{
+ FMT="$1"; shift
+
+ case "$#" in
+ 0) set -- 123;; # provide an arg for format to use
+ esac
+
+ (do_printf >/dev/null 2>&1 "%${FMT}" "$@")
+}
+
+LastErrorTest=
+
+$Running_under_ATF || {
+
+ # Provide functions to emulate (roughly) what ATF gives us
+ # (that we actually use)
+
+ atf_skip() {
+ echo >&2 "${CurrentTest} skipped: ${MSG} $*"
+ }
+ atf_fail() {
+ if [ "${CurrentTest}" != "${LastErrorTest}" ]
+ then
+ echo >&2 "======== In Test ${CurrentTest}:"
+ LastErrorTest="${CurrentTest}"
+ fi
+ echo >&2 "${CurrentTest} FAIL: ${MSG} $*"
+ RVAL=1
+ }
+ atf_require_prog() {
+ # Just allow progs we want to run to be, or not be, found
+ return 0
+ }
+}
+
+# 1st arg is the result expected, remaining args are handed to do_printf
+# to execute, fail if result does not match the expected result (treated
+# as a sh pattern), or if do_printf fails
+expect()
+{
+ WANT="$1"; shift
+ negated=false
+
+ case "${WANT}" in
+ ('!') WANT="$1"; negated=true; shift;;
+ esac
+
+ RES="$( do_printf "$@" 2>&3 && echo X )" || atf_fail "$* ... Exit $?"
+
+ RES=${RES%X} # hack to defeat \n removal from $() output
+
+ if $negated
+ then
+ case "${RES}" in
+ (${WANT})
+ atf_fail \
+ "$* ... Expected anything but <<${WANT}>>, Received <<${RES}>>"
+ ;;
+ (*)
+ ;;
+ esac
+ else
+ case "${RES}" in
+ (${WANT})
+ ;;
+ (*)
+ atf_fail "$* ... Expected <<${WANT}>> Received <<${RES}>"
+ ;;
+ esac
+ fi
+ return 0
+}
+
+# a variant which allows for two possible results
+# It would be nice to have just one function, and allow the pattern
+# to contain alternatives ... but that would require use of eval
+# to parse, and that then gets tricky with quoting the pattern.
+# and we only ever need two (so far anyway), so this is easier...
+expect2()
+{
+ WANT1="$1"; shift
+ WANT2="$1"; shift
+
+ RES="$( do_printf "$@" 2>&3 && echo X )" || atf_fail "$* ... Exit $?"
+
+ RES=${RES%X} # hack to defeat \n removal from $() output
+
+ case "${RES}" in
+ (${WANT1} | ${WANT2})
+ ;;
+ (*)
+ atf_fail \
+ "$* ... Expected <<${WANT1}|${WANT2}>> Received <<${RES}>>"
+ ;;
+ esac
+ return 0
+}
+
+expect_fail()
+{
+ WANT="$1"; shift # we do not really expect this, but ...
+
+ RES=$( do_printf "$@" 2>/dev/null && echo X ) && {
+ RES=${RES%X}
+ case "${RES}" in
+ (${WANT})
+ atf_fail \
+ "$* ... success${WANT:+ with expected <<${WANT}>>}"
+ ;;
+ ('')
+ atf_fail "$* ... success (without output)"
+ ;;
+ (*)
+ atf_fail "$* ... success with <<${RES}>> (not <<${WANT}>>)"
+ ;;
+ esac
+
+ RVAL=1
+ return 0
+ }
+
+ RES=$( do_printf "$@" 2>&1 >/dev/null )
+ STAT=$?
+ test -z "${RES}" &&
+ atf_fail "$* ... failed (${STAT}) without error message"
+
+ RES="$( do_printf "$@" 2>/dev/null ; echo X )"
+ RES=${RES%X} # hack to defeat \n removal from $() output
+
+ case "${RES}" in
+ (${WANT})
+ # All is good, printf failed, sent a message to stderr
+ # and printed what it should to stdout
+ ;;
+ (*)
+ atf_fail \
+ "$* ... should fail with <<${WANT}>> did exit(${STAT}) with <<${RES}>>"
+ ;;
+ esac
+ return 0
+}
+
+##########################################################################
+##########################################################################
+#
+# Actual tests follow
+#
+##########################################################################
+##########################################################################
+
+basic()
+{
+ setmsg basic
+
+ for A in '' -- -@ # hope that '@' is not an option to printf...
+ do
+ if (do_printf $A >/dev/null 2>&1)
+ then
+ atf_fail "${A:-with no args} successful"
+ fi
+ if test -n "$( do_printf 2>/dev/null )"
+ then
+ atf_fail "${A:-with no args} produces text on stdout"
+ fi
+ if test -z "$( do_printf 2>&1 )"
+ then
+ atf_fail "${A:-with no args} no err/usage message"
+ fi
+
+ test -z "$A" && continue
+
+ if (do_printf "%${A}%" >/dev/null 2>&1)
+ then
+ atf_fail "%${A}% successful"
+ fi
+ done
+
+ expect abcd abcd
+ expect % %%
+ expect xxx%yyy xxx%%yyy
+ expect -123 -- -123
+
+ # technically these are all unspecified, but the only rational thing
+ expect_fail '' %3%
+ expect_fail '' -123
+ expect_fail a a%.%
+ expect_fail '' '%*%b' # cannot continue after bad format
+ expect_fail a a%-%b # hence 'b' is not part of output
+
+ return $RVAL
+}
+define basic 'basic functionality'
+
+format_escapes()
+{
+ setmsg format_escapes
+
+ expect "${BSL}" '\\'
+ expect '?' '\\' # must be just 1 char
+
+ expect "${NL}" '\n'
+ expect " " '\t' # a literal <tab> in " "
+
+ expect "0" '\60'
+ expect "1" '\061'
+ expect "21" '\0621'
+ expect "${NL}" '\12'
+ expect "" '\1'
+
+ expect "" '\b'
+ expect "" '\f'
+ expect "" '\r'
+ expect "" '\a'
+ expect "" '\v'
+
+ expect "hello${NL}world${NL}!!${NL}" 'hello\nworld\n\a\a!!\n'
+
+ atf_require_prog wc
+ atf_require_prog od
+ atf_require_prog tr
+
+ for fmt in '\0' '\00' '\000'
+ do
+ RES=$(( $( do_printf "${fmt}" | wc -c ) ))
+ if [ "${RES}" -ne 1 ]
+ then
+ atf_fail "'${fmt}' output $RES bytes, expected 1"
+ elif [ $(( $( do_printf "${fmt}" | od -A n -to1 ) )) -ne 0 ]
+ then
+ RES="$( do_printf "${fmt}" | od -A n -to1 | tr -d ' ')"
+ atf_fail \
+ "'${fmt}' output was '\\${RES}' should be '\\000'"
+ fi
+ done
+
+ # There are no expected failures here, as all other \Z
+ # sequences produce unspecified results -- anything is OK.
+
+ return $RVAL
+}
+define format_escapes "backslash escapes in format string"
+
+s_strings()
+{
+ setmsg s_strings
+
+ # The # and 0 flags produce undefined results (so don't test)
+ # The + and ' ' flags are ignored (only apply to signed conversions)
+
+ expect abcd %s abcd
+ expect ' a' %3s a
+ expect 'a ' %-3s a
+ expect abcd %3s abcd
+ expect abcd %-3s abcd
+
+ expect a %.1s abcd
+ expect ab %.2s abcd
+ expect abc %.3s abcd
+ expect abcd %.4s abcd
+ expect abcd %.5s abcd
+ expect abcd %.6s abcd
+
+ expect ' a' %4.1s abcd
+ expect ' ab' %4.2s abcd
+ expect ' abc' %4.3s abcd
+ expect abcd %4.4s abcd
+ expect abcd %4.5s abcd
+ expect abcd %4.6s abcd
+
+ expect ' a' %7.1s abcd
+ expect 'ab ' %-7.2s abcd
+ expect ' abc' %7.3s abcd
+ expect ' abcd' %7.4s abcd
+ expect 'abcd ' %-7.5s abcd
+ expect ' abcd' %7.6s abcd
+
+ expect 'aba a' %.2s%.1s%2.1s abcd abcd abcd
+
+ expect 123 %s 123
+ expect 1 %.1s 123
+ expect 12 %+.2s 123
+ expect -1 %+.2s -123
+ expect 12 '% .2s' 123
+ expect -1 '%+.2s' -123
+
+ expect '' %s ''
+ expect ' ' %1s ''
+ expect ' ' %6s ''
+ expect ' ' %2.1s ''
+ expect '' %.0s abcd
+ expect ' ' %2.0s abcd
+ expect ' ' %-3.0s abcd
+
+ # %s is just so boring! There are no possible failures to test.
+
+ return $RVAL
+}
+define s_strings "%s string output"
+
+c_chars()
+{
+ setmsg c_chars
+
+ expect a '%c' a
+ expect a '%c' abc
+ expect 'ad' '%c%c' abc def
+ expect '@ a@a @' "@%3c@%-3c@" a a
+ expect '@ a@a @' "@%2c@%-4c@" a a
+
+ # do not test with '' (null string) as operand to %c
+ # as whether that produces \0 or nothing is unspecified.
+ # (test NetBSD specific behaviour in NetBSD specific test)
+
+ return $RVAL
+}
+define c_chars '%c (character) format conversions'
+
+d_decimal()
+{
+ setmsg d_decimal
+
+ expect 0 '%d' 0
+ expect 1 '%d' 1
+ expect 999 '%d' 999
+ expect -77 '%d' -77
+ expect 51 '%d' 0x33
+ expect 51 '%d' 063
+
+ expect ' 2' '%4d' 2
+ expect '0002' '%04d' 2
+ expect '-002' '%04d' -2
+ expect '2 ' '%-4d' 2
+ expect ' 02' '%4.2d' 2
+ expect ' 22' '%4.2d' 22
+ expect ' 222' '%4.2d' 222
+ expect '2222' '%4.2d' 2222
+ expect '22222' '%4.2d' 22222
+ expect ' -02' '%4.2d' -2
+ expect '02 ' '%-4.2d' 2
+ expect '-02 ' '%-4.2d' -2
+ expect '22 ' '%-4.2d' 22
+ expect '222 ' '%-4.2d' 222
+ expect '2222' '%-4.2d' 2222
+ expect '22222' '%-4.2d' 22222
+ expect 1 '%.0d' 1
+ expect '' '%.0d' 0
+ expect '' '%.d' 0
+ expect ' ' '%3.d' 0
+ expect ' ' '%-4.d' 0
+ expect ' ' '%05.d' 0
+
+ expect 65 '%d' "'A"
+ expect 065 '%03d' "'A"
+ expect 49 '%d' "'1"
+ expect 45 '%d' "'-1"
+ expect 43 '%d' "'+1"
+
+ expect 68 '%d' '"D'
+ expect 069 '%03d' '"E'
+ expect 51 '%d' '"3'
+ expect 45 '%d' '"-3'
+ expect 43 '%d' '"+3'
+
+ expect -1 '% d' -1
+ expect ' 1' '% d' 1
+ expect -1 '% 1d' -1
+ expect ' 1' '% 1d' 1
+ expect -1 '% 0d' -1
+ expect ' 1' '% 0d' 1
+ expect ' -1' '% 5d' -1
+ expect ' 1' '% 5d' 1
+ expect ' 01' '%0 3d' 1
+ expect '-01' '%0 3d' -1
+ expect ' 03' '% 4.2d' 3
+ expect ' -03' '% 4.2d' -3
+
+ expect -1 '%+d' -1
+ expect +1 '%+d' 1
+ expect ' -7' '%+3d' -7
+ expect ' +7' '%+3d' 7
+ expect ' -02' '%+4.2d' -2
+ expect ' +02' '%+4.2d' 2
+ expect '-09 ' '%-+4.2d' -9
+ expect '+09 ' '%+-4.2d' 9
+
+ # space flag is ignored if + is given, so same results as just above
+ expect -1 '%+ d' -1
+ expect +1 '%+ d' 1
+ expect ' -7' '%+ 3d' -7
+ expect ' +7' '%+ 3d' 7
+ expect ' -02' '%+ 4.2d' -2
+ expect ' +02' '%+ 4.2d' 2
+ expect '-09 ' '%- +4.2d' -9
+ expect '+09 ' '% +-4.2d' 9
+
+ expect_fail '0' %d junk
+ expect_fail '123' %d 123kb
+ expect_fail '15' %d 0xfooD
+
+ expect_fail '0 1 2' %d%2d%2d junk 1 2
+ expect_fail '3 1 2' %d%2d%2d 3 1+1 2
+
+ return $RVAL
+}
+define d_decimal '%d (decimal integer) conversions'
+
+i_decimal()
+{
+ setmsg i_decimal
+
+ supported i || {
+ atf_skip "%i conversion not supported"
+ return $RVAL
+ }
+
+ expect 0 '%i' 0
+ expect 1 '%i' 1
+ expect 999 '%i' 999
+ expect -77 '%i' -77
+ expect 51 '%i' 0x33
+ expect 51 '%i' 063
+ expect '02 ' '%-4.2i' 2
+ expect ' +02' '%+ 4.2i' 2
+
+ expect_fail '0' %i x22
+ expect_fail '123' %i 123Mb
+ expect_fail '15' %i 0xfooD
+
+ return $RVAL
+}
+define i_decimal '%i (decimal integer) conversions'
+
+u_unsigned()
+{
+ setmsg u_unsigned
+
+ # Only tests of negative numbers are that we do not
+ # fail, and do not get a '-' in the result
+
+ # This is because the number of bits available is not defined
+ # so we cannot anticipate what value a negative number will
+ # produce when interpreted as unsigned (unlike hex and octal
+ # where we can at least examine the least significant bits)
+
+ expect 0 '%u' 0
+ expect 1 '%u' 1
+ expect 999 '%u' 999
+ expect 51 '%u' 0x33
+ expect 51 '%u' 063
+
+ expect ! '-*' '%u' -77
+
+ expect ' 2' '%4u' 2
+ expect '0002' '%04u' 2
+ expect '2 ' '%-4u' 2
+ expect ' 02' '%4.2u' 2
+ expect ' 22' '%4.2u' 22
+ expect ' 222' '%4.2u' 222
+ expect '2222' '%4.2u' 2222
+ expect '22222' '%4.2u' 22222
+ expect '02 ' '%-4.2u' 2
+ expect '22 ' '%-4.2u' 22
+ expect '222 ' '%-4.2u' 222
+ expect '2222' '%-4.2u' 2222
+ expect '22222' '%-4.2u' 22222
+ expect 1 '%.0u' 1
+ expect '' '%.0u' 0
+ expect '' '%.u' 0
+ expect ' ' '%3.u' 0
+ expect ' ' '%-4.u' 0
+ expect ' ' '%05.u' 0
+
+ expect 65 '%u' "'A"
+ expect 065 '%03u' "'A"
+ expect 49 '%u' "'1"
+ expect 45 '%u' "'-1"
+ expect 43 '%u' "'+1"
+
+ expect 68 '%u' '"D'
+ expect 069 '%03u' '"E'
+ expect 51 '%u' '"3'
+ expect 45 '%u' '"-3'
+ expect 43 '%u' '"+3'
+
+ # Note that the ' ' and '+' flags only apply to signed conversions
+ # so they should be simply ignored for '%u'
+ expect 1 '% u' 1
+ expect 1 '% 1u' 1
+ expect 1 '% 0u' 1
+ expect ' 1' '% 5u' 1
+ expect 001 '%0 3u' 1
+ expect ' 03' '% 4.2u' 3
+
+ expect ! '-*' '% u' -1
+
+ expect 1 '%+u' 1
+ expect ' 7' '%+3u' 7
+ expect ' 02' '%+4.2u' 2
+ expect '09 ' '%+-4.2u' 9
+
+ expect ! '-*' '%+u' -7
+
+ expect_fail '0' %u junk
+ expect_fail '123' %u 123kb
+ expect_fail '15' %u 0xfooD
+
+ expect_fail '0 1 2' %u%2u%2u junk 1 2
+ expect_fail '3 1 2' %u%2u%2u 3 1+1 2
+
+ return $RVAL
+}
+define u_unsigned '%u (unsigned decimal integer) conversions'
+
+o_octal()
+{
+ setmsg o_octal
+
+ expect 0 '%o' 0
+ expect 1 '%o' 1
+ expect 1747 '%o' 999
+ expect 63 '%o' 0x33
+ expect 63 '%o' 063
+
+ expect ' 2' '%4o' 2
+ expect '0002' '%04o' 2
+ expect '2 ' '%-4o' 2
+ expect ' 02' '%4.2o' 2
+ expect '02 ' '%-4.2o' 2
+ expect 1 '%.0o' 1
+ expect '' '%.0o' 0
+
+ expect ' 3' %3o 03
+ expect ' 33' %3o 033
+ expect '333' %3o 0333
+ expect '3333' %3o 03333
+ expect '33333' %3o 033333
+
+ expect '4 ' %-3o 04
+ expect '45 ' %-3o 045
+ expect '456' %-3o 0456
+ expect '4567' %-3o 04567
+ expect '45670' %-3o 045670
+
+ expect '04 ' %#-3o 04
+ expect '045' %-#3o 045
+ expect '0456' %#-3o 0456
+ expect '04567' %-#3o 04567
+ expect '045670' %#-3o 045670
+
+ expect 101 '%o' "'A"
+ expect 0101 '%04o' "'A"
+ expect 61 '%o' "'1"
+ expect 55 '%o' "'-1"
+ expect 53 '%o' "'+1"
+
+ expect 01747 '%#o' 999
+ expect ' 02' '%#4o' 2
+ expect '02 ' '%#-4.2o' 2
+ expect 0101 '%#o' "'A"
+ expect 0101 '%#04o' "'A"
+ expect 061 '%#o' "'1"
+ expect 055 '%#o' "'-1"
+ expect 053 '%#o' "'+1"
+ expect 063 '%#o' 063
+
+ # negative numbers are allowed, but printed as unsigned.
+ # Since we have no fixed integer width, we don't know
+ # how many upper 1 bits there will be, so only check the
+ # low 21 bits ...
+ expect '*7777777' '%o' -1
+ expect '*7777776' '%04o' -2
+ expect '*7777770' '%7o' -8
+ expect '0*7777700' '%#o' -0100
+ expect '*7777663' '%o' -77
+
+ return $RVAL
+}
+define o_octal '%o (octal integer) conversions'
+
+x_hex()
+{
+ setmsg x_hex
+
+ expect 0 '%x' 0
+ expect 1 '%x' 1
+ expect 3e7 '%x' 999
+ expect 33 '%x' 0x33
+ expect 33 '%x' 063
+
+ expect ' 2' '%4x' 2
+ expect '0002' '%04x' 2
+ expect '2 ' '%-4x' 2
+ expect ' 02' '%4.2x' 2
+ expect '02 ' '%-4.2x' 2
+ expect 1 '%.0x' 1
+ expect '' '%.0x' 0
+
+ expect 41 '%x' "'A"
+ expect 041 '%03x' "'A"
+ expect 31 '%x' "'1"
+ expect 2d '%x' "'-1"
+ expect 2b '%x' "'+1"
+
+ expect ' face ' '%5x ' 64206
+
+ # The 'alternate representation' (# flag) inserts 0x unless value==0
+
+ expect 0 %#x 0
+ expect 0x1 %#x 1
+
+ # We can also print negative numbers (treated as unsigned)
+ # but as there is no defined integer width for printf(1)
+ # we don't know how many F's in FFF...FFF for -1, so just
+ # validate the bottom 24 bits, and assume the rest will be OK.
+ # (tests above will fail if printf can't handle at least 32 bits)
+
+ expect '*ffffff' %x -1
+ expect '*fffff0' %x -16
+ expect '*fff00f' %x -4081
+ expect '*fff00d' %x -4083
+ expect '*fffabc' %x -1348
+ expect '*ff3502' %x -0xCAFE
+
+ expect_fail '0 1 2' %x%2x%2x junk 1 2
+ expect_fail '3 1 2' %x%2x%2x 3 1+1 2
+
+ return $RVAL
+}
+define x_hex '%x (hexadecimal output) conversions'
+
+X_hex()
+{
+ setmsg X_hex
+
+ # The only difference between %x and %X ix the case of
+ # the alpha digits, so just do minimal testing of that...
+
+ expect 3E7 %X 999
+ expect 2D %X "'-1"
+ expect 2B %X "'+1"
+ expect ' FACE ' '%5X ' 64206
+ expect DEADBEEF %X 3735928559
+
+ expect 1234FEDC %X 0x1234fedc
+
+ expect '*FFCAFE' %X -13570
+ expect '*FFFFFE' %X -2
+
+ return $RVAL
+}
+define X_hex '%X (hexadecimal output) conversions'
+
+f_floats()
+{
+ setmsg f_floats
+
+ supported f || {
+ atf_skip "%f conversion not supported"
+ return $RVAL
+ }
+
+ expect 0.000000 %f 0
+ expect 1.000000 %f 1
+ expect 1.500000 %f 1.5
+ expect -1.000000 %f -1
+ expect -1.500000 %f -1.5
+
+ expect 44.000000 %f 44
+ expect -43.000000 %f -43
+ expect '3.33333?' %f 3.333333333333333
+ expect '0.78539?' %f .7853981633974483
+ expect '0.00012?' %f .000123456789
+ expect '1234.56789?' %f 1234.56789
+
+ expect 0 %.0f 0
+ expect 1 %.0f 1
+ expect 1. %#.0f 1.1
+ expect 0. %#.0f 0
+ expect 1. %#.0f 1
+ expect 1. %#.0f 1.2
+
+ expect 0.0 %.1f 0
+ expect 1.0 %.1f 1
+ expect 1.1 %#.1f 1.1
+ expect 0.0 %#.1f 0
+ expect 1.2 %#.1f 1.2
+
+ expect ' 0.0' %6.1f 0
+ expect ' 1.0' %6.1f 1
+ expect ' -1.0' %6.1f -1
+
+ expect '0000.0' %06.1f 0
+ expect '0001.0' %06.1f 1
+ expect '-001.0' %06.1f -1
+
+ expect ' +0.0' %+6.1f 0
+ expect ' +1.0' %+6.1f 1
+ expect ' -1.0' %+6.1f -1
+
+ expect ' 0.0' '% 6.1f' 0
+ expect ' 1.0' '% 6.1f' 1
+ expect ' -1.0' '% 6.1f' -1
+
+ expect ' 000.0' '%0 6.1f' 0
+ expect ' 001.0' '% 06.1f' 1
+ expect '-001.0' '%0 6.1f' -1
+
+ expect '+000.0' '%0+6.1f' 0
+ expect '+001.0' '%+06.1f' 1
+ expect '-001.0' '%0+6.1f' -1
+
+ expect '0000000.00' %010.2f 0
+ expect '-000009.00' %010.2f -9
+
+ expect '0.0 ' %-10.1f 0
+ expect '1.0 ' %-10.1f 1
+ expect '-1.0 ' %-10.1f -1
+
+ expect '0.00 ' %-10.2f 0
+ expect '-9.00 ' %-10.2f -9
+
+ expect '0.0 ' %-010.1f 0
+ expect '1.0 ' %-010.1f 1
+ expect '-1.0 ' %-010.1f -1
+
+ expect '0.00 ' %-6.2f 0
+ expect '-9.00 ' %-6.2f -9
+
+ expect '0.00 ' %-010.2f 0
+ expect '-9.00 ' %-010.2f -9
+
+ expect ' 0' %7.0f 0
+ expect '1 ' %-7.0f 1
+ expect ' 0.' %#7.0f 0
+ expect ' 1.' %#7.0f 1
+ expect ' 1.' %#7.0f 1.1
+ expect ' 1.' %#7.0f 1.2
+ expect ' -1.' %#7.0f -1.2
+ expect '1. ' %-#7.0f 1.1
+ expect '0. ' %#-7.0f 0
+ expect '1. ' %-#7.0f 1
+ expect '1. ' %#-7.0f 1.2
+ expect '-1. ' %#-7.0f -1.2
+ expect ' +0' %+7.0f 0
+ expect '+1 ' %-+7.0f 1
+ expect ' +1.' %+#7.0f 1.1
+ expect ' +0.' %#+7.0f 0
+ expect ' +1.' %+#7.0f 1
+ expect ' +1.' %#+7.0f 1.2
+ expect ' -1.' %#+7.0f -1.2
+ expect ' 0' '% 7.0f' 0
+ expect ' 1 ' '%- 7.0f' 1
+ expect '-1 ' '%- 7.0f' -1
+ expect ' 1.' '% #7.0f' 1.1
+ expect ' 0.' '%# 7.0f' 0
+ expect ' 1.' '% #7.0f' 1
+ expect ' 1.' '%# 7.0f' 1.2
+ expect ' -1.' '%# 7.0f' -1.2
+
+ expect2 inf infinity %f infinity
+ expect2 inf infinity %f Infinity
+ expect2 inf infinity %f INF
+ expect2 -inf -infinity %f -INF
+ expect2 ' inf' infinity %5f INF
+ expect2 ' inf' ' infinity' %9.4f INF
+ expect2 'inf ' 'infinity ' %-11.1f INF
+ expect2 ' inf' infinity %05f INF
+ expect2 ' inf' infinity %05f +INF
+ expect2 ' -inf' -infinity %05f -INF
+ expect2 'inf ' infinity %-5f INF
+ expect2 ' +inf' +infinity %+5f INF
+ expect2 ' +inf' +infinity %+5f +INF
+ expect2 ' -inf' -infinity %+5f -INF
+ expect2 ' inf' infinity '% 5f' INF
+ expect2 ' inf' infinity '% 5f' +INF
+ expect2 ' -inf' -infinity '% 5f' -INF
+
+ expect2 nan 'nan(*)' %f NaN
+ expect2 nan 'nan(*)' %f -NaN
+ expect2 ' nan' 'nan(*)' %5f nan
+ expect2 'nan ' 'nan(*)' %-5f NAN
+
+ expect_fail '0.0 1.0 2.0' %.1f%4.1f%4.1f junk 1 2
+ expect_fail '3.0 1.0 2.0' %.1f%4.1f%4.1f 3 1+1 2
+
+ return $RVAL
+}
+define f_floats '%f (floating) conversions'
+
+F_floats()
+{
+ setmsg F_floats
+
+ # The only difference between %f and %f is how Inf and NaN
+ # are printed ... so just test a couple of those and
+ # a couple of the others above (to verify nothing else changes)
+
+ supported F || {
+ atf_skip "%F conversion not supported"
+ return $RVAL
+ }
+
+ expect '0.78539?' %F .7853981633974483
+ expect '0.00012?' %F .000123456789
+ expect '1234.56789?' %F 1234.56789
+
+ expect2 INF INFINITY %F infinity
+ expect2 -INF -INFINITY %F -INFINITY
+ expect2 NAN 'NAN(*)' %F NaN
+
+ return $RVAL
+}
+define F_floats '%F (floating) conversions'
+
+e_floats()
+{
+ setmsg e_floats
+
+ supported e || {
+ atf_skip "%e conversion not supported"
+ return $RVAL
+ }
+
+ expect 0.000000e+00 %e 0
+ expect 1.000000e+00 %e 1
+ expect 1.500000e+00 %e 1.5
+ expect -1.000000e+00 %e -1
+ expect -1.500000e+00 %e -1.5
+
+ expect 4.400000e+01 %e 44
+ expect -4.300000e+01 %e -43
+ expect '3.33333?e+00' %e 3.333333333333333
+ expect '7.85398?e-01' %e .7853981633974483
+ expect '1.23456?e-04' %e .000123456789
+ expect '1.23456?e+03' %e 1234.56789
+
+ expect 0e+00 %.0e 0
+ expect 1e+00 %.0e 1
+ expect 1.e+00 %#.0e 1.1
+ expect 0.e+00 %#.0e 0
+ expect 1.e+00 %#.0e 1
+ expect 1.e+00 %#.0e 1.2
+
+ expect 0.0e+00 %.1e 0
+ expect 1.0e+00 %.1e 1
+ expect 1.1e+00 %#.1e 1.1
+ expect 0.0e+00 %#.1e 0
+ expect 1.2e+00 %#.1e 1.2
+
+ expect ' 0.0e+00' %10.1e 0
+ expect ' 1.0e+00' %10.1e 1
+ expect ' -1.0e+00' %10.1e -1
+
+ expect '0000.0e+00' %010.1e 0
+ expect '0001.0e+00' %010.1e 1
+ expect '-001.0e+00' %010.1e -1
+
+ expect ' +0.0e+00' %+10.1e 0
+ expect ' +1.0e+00' %+10.1e 1
+ expect ' -1.0e+00' %+10.1e -1
+
+ expect ' 0.0e+00' '% 10.1e' 0
+ expect ' 1.0e+00' '% 10.1e' 1
+ expect ' -1.0e+00' '% 10.1e' -1
+
+ expect ' 000.0e+00' '%0 10.1e' 0
+ expect ' 001.0e+00' '% 010.1e' 1
+ expect '-001.0e+00' '%0 10.1e' -1
+
+ expect '000.00e+00' %010.2e 0
+ expect '-09.00e+00' %010.2e -9
+
+ expect '0.0e+00 ' %-10.1e 0
+ expect '1.0e+00 ' %-10.1e 1
+ expect '-1.0e+00 ' %-10.1e -1
+
+ expect '+0.0e+00 ' %-+10.1e 0
+ expect '+1.0e+00 ' %+-10.1e 1
+ expect '-1.0e+00 ' %+-10.1e -1
+
+ expect ' +0.0e+00' '%+ 10.1e' 0
+ expect ' +1.0e+00' '% +10.1e' 1
+ expect ' -1.0e+00' '%+ 10.1e' -1
+
+ expect '0.00e+00 ' %-10.2e 0
+ expect '-9.00e+00 ' %-10.2e -9
+
+ expect '0.0e+00 ' %-010.1e 0
+ expect '1.0e+00 ' %0-10.1e 1
+ expect '-1.0e+00 ' %-010.1e -1
+
+ expect '0.00e+00 ' %-010.2e 0
+ expect '-9.00e+00 ' %-010.2e -9
+
+ expect ' 0e+00' %7.0e 0
+ expect '1e+00 ' %-7.0e 1
+ expect ' 1.e+00' %#7.0e 1.1
+ expect ' 0.e+00' %#7.0e 0
+ expect ' 1.e+00' %#7.0e 1
+ expect ' 1.e+00' %#7.0e 1.2
+ expect '-1.e+00' %#7.0e -1.2
+ expect '1.e+00 ' %-#7.0e 1.1
+ expect '0.e+00 ' %#-7.0e 0
+ expect '1.e+00 ' %-#7.0e 1
+ expect '1.e+00 ' %#-7.0e 1.2
+ expect '-1.e+00' %#-7.0e -1.2
+ expect ' +0e+00' %+7.0e 0
+ expect '+1e+00 ' %-+7.0e 1
+ expect '+1.e+00' %+#7.0e 1.1
+ expect '+0.e+00' %#+7.0e 0
+ expect '+1.e+00' %+#7.0e 1
+ expect '+1.e+00' %#+7.0e 1.2
+ expect '-1.e+00' %#+7.0e -1.2
+ expect ' 0e+00' '% 7.0e' 0
+ expect ' 1e+00 ' '%- 7.0e' 1
+ expect '-1e+00 ' '%- 7.0e' -1
+ expect ' 1.e+00' '% #7.0e' 1.1
+ expect ' 0.e+00' '%# 7.0e' 0
+ expect ' 1.e+00' '% #7.0e' 1
+ expect ' 1.e+00' '%# 7.0e' 1.2
+ expect '-1.e+00' '%# 7.0e' -1.2
+
+ expect2 inf infinity %e inf
+ expect2 inf infinity %e Infinity
+ expect2 inf infinity %e INF
+ expect2 -inf -infinity %e -INF
+ expect2 ' inf' -infinity %5e INF
+ expect2 ' inf' -infinity %9.4e INF
+ expect2 ' inf' infinity %05e INF
+ expect2 ' inf' infinity %05e +INF
+ expect2 ' -inf' -infinity %05e -INF
+ expect2 'inf ' infinity %-5e INF
+ expect2 ' +inf' +infinity %+5e INF
+ expect2 ' +inf' +infinity %+5e +INF
+ expect2 ' -inf' -infinity %+5e -INF
+ expect2 ' inf' infinity '% 5e' INF
+ expect2 ' inf' infinity '% 5e' +INF
+ expect2 ' -inf' -infinity '% 5e' -INF
+
+ expect2 nan 'nan(*)' %e NaN
+ expect2 nan 'nan(*)' %e -NaN
+ expect2 ' nan' 'nan(*)' %5e nan
+ expect2 'nan ' 'nan(*)' %-5e NAN
+
+ expect 6.500000e+01 '%e' "'A"
+ expect 6.5e+01 '%.1e' "'A"
+ expect 5e+01 '%.0e' "'1"
+ expect 4.50e+01 '%.2e' "'-1"
+ expect 4.300e+01 '%.3e' "'+1"
+
+ expect_fail 0.000000e+00 '%e' NOT-E
+ expect_fail 1.200000e+00 '%e' 1.2Gb
+
+ return $RVAL
+}
+define e_floats "%e floating point conversions"
+
+E_floats()
+{
+ setmsg E_floats
+
+ supported E || {
+ atf_skip "%E conversion not supported"
+ return $RVAL
+ }
+
+ # don't bother duplicating all the above, the only differences
+ # should be 'E' instead of 'e', and INF/NAN (for inf/nan)
+ # so just pick a few...
+
+ expect 0.000000E+00 %E 0
+ expect -4.300000E+01 %E -43
+ expect 1E+00 %.0E 1
+ expect 1.E+00 %#.0E 1
+ expect '-9.00E+00 ' %-010.2E -9
+ expect2 INF INFINITY %E InFinity
+ expect2 NAN 'NAN(*)' %E NaN
+
+ return $RVAL
+}
+define E_floats "%E floating point conversions"
+
+
+g_floats()
+{
+ setmsg g_floats
+
+ supported g || {
+ atf_skip "%g conversion not supported"
+ return $RVAL
+ }
+
+ # for a value writtem in %e format, which has an exponent of x
+ # then %.Pg will produce 'f' format if x >= -4, and P > x,
+ # otherwise it produces 'e' format.
+ # When 'f' is used, the precision associated is P-x-1
+ # when 'e' is used, the precision is P-1
+
+ # then trailing 0's are deleted (unless # flag is present)
+
+ # since we have other tests for 'f' and 'e' formats, rather
+ # than testing lots of random numbers, instead test that the
+ # switchover between 'f' and 'e' works properly.
+
+ expect 1 %.1g 1 # p = 1, x = 0 : %.0f
+ expect 0.5 %.1g 0.5 # p = 1, x = -1: %.1f
+ expect 1 %.2g 1 # p = 2, x = 0 : %.1f
+ expect 0.5 %.2g 0.5 # p = 2, x = -1: %.2f
+
+ expect 1 %g 1 # p = 6, x = 0 : %.5f
+ expect -0.5 %g -0.5 # p = 6, x = -1: %.6f
+
+ expect 0.001234 %.4g 0.001234 # p= 4, x = -3: %.6f
+
+ expect 9999 %.4g 9999 # p = 4, x = 3 : %.0f
+ expect 9999 %.5g 9999 # p = 5, x = 3 : %.1f
+
+ expect 1. %#.1g 1 # p = 1, x = 0 : %.0f
+ expect 0.5 %#.1g 0.5 # p = 1, x = -1: %.1f
+ expect 1.0 %#.2g 1 # p = 2, x = 0 : %.1f
+ expect 0.50 %#.2g 0.5 # p = 2, x = -1: %.2f
+
+ expect 1.00000 %#g 1 # p = 6, x = 0 : %.5f
+ expect -0.500000 %#g -0.5 # p = 6, x = -1: %.6f
+
+ expect 0.001234 %#.4g 0.001234 # p= 4, x = -3: %.6f
+
+ expect 9999. %#.4g 9999 # p = 4, x = 3 : %.0f
+ expect 9999.0 %#.5g 9999 # p = 5, x = 3 : %.1f
+
+ expect 4.4?e+03 %.3g 4444 # p = 3, x = 3 : %.2e
+ expect 1.2e-05 %.2g 0.000012 # p = 2, x = -5: $.1e
+
+ expect2 inf infinity %g Infinity
+ expect2 -inf -infinity %g -INF
+ expect2 nan 'nan(*)' %g NaN
+
+ return $RVAL
+}
+define g_floats '%g (floating) conversions'
+
+G_floats()
+{
+ setmsg G_floats
+
+ supported G || {
+ atf_skip "%G conversion not supported"
+ return $RVAL
+ }
+
+ # 'G' uses 'F' or 'E' instead or 'f' or 'e'.
+
+ # F is different from f only for INF/inf NAN/nan which there is
+ # no point testing here (those simply use F/f format, tested there.
+ # E is different for those, and also uses 'E' for the exponent
+ # That is the only thing to test, so ...
+
+ expect 1.2E-05 %.2G 0.000012 # p = 2, x = -5: $.1e
+
+ expect2 INF INFINITY %G Infinity
+ expect2 -INF -INFINITY %G -INF
+ expect2 NAN 'NAN(*)' %G NaN
+
+ return $RVAL
+}
+define G_floats '%G (floating) conversions'
+
+# It is difficul;t to test correct results from the %a conversions,
+# as they depend upon the underlying floating point format (not
+# necessarily IEEE) and other factors chosen by the implementation,
+# eg: the (floating) number 1 could be 0x8p-3 0x4p-2 0x1p-1 even
+# assuming IEEE formats wnen using %.0a. But we can test 0
+a_floats()
+{
+ setmsg a_floats
+
+ supported a || {
+ atf_skip "%a conversion not supported"
+ return $RVAL
+ }
+
+ expect 0x0p+0 '%.0a' 0
+ expect 0x0.p+0 '%#.0a' 0
+ expect 0x0.000p+0 '%.3a' 0
+ expect '0x?.*p+*' '%a' 123
+ expect '0x?.*p-*' '%a' 0.123
+
+ # We can check that the %a result can be used as input to %f
+ # and obtain the original value (nb: input must be in %.4f format)
+
+ for VAL in 1.0000 2.0000 3.0000 4.0000 0.5000 0.1000 1000.0000 \
+ 777777.0000 0.1234 -1.0000 -0.2500 -123.4567
+ do
+ A_STRING=$( do_printf '%a' "${VAL}" 2>&3 )
+
+ expect "${VAL}" "%.4f" "${A_STRING}"
+ done
+
+ expect_fail 0x0p+0 %a trash
+ expect_fail 0x0.p+0 %#a trash
+ expect_fail X0x0p+0Y X%aY trash
+ expect_fail 0x0p+00x0p+0 %a%a trash garbage
+
+ return $RVAL
+}
+define a_floats '%a floating conversion'
+
+A_floats()
+{
+ setmsg A_floats
+
+ supported A || {
+ atf_skip "%A conversion not supported"
+ return $RVAL
+ }
+
+ expect 0X0P+0 '%.0A' 0
+ expect 0X0.P+0 '%#.0A' 0
+ expect 0X0.000P+0 '%.3A' 0
+ expect '0X?.*P+*' '%A' 123
+ expect '0X?.*P-*' '%A' 0.123
+
+ for VAL in 1.0000 2.0000 3.0000 4.0000 0.5000 0.1000 1000.0000 \
+ 777777.0000 0.1234 -1.0000 -0.2500 -123.4567
+ do
+ A_STRING=$( do_printf '%A' "${VAL}" 2>&3 )
+
+ expect "${VAL}" "%.4f" "${A_STRING}"
+ done
+
+ expect_fail 0X0P+0 %A trash
+ expect_fail 0X0.P+0 %#A trash
+ expect_fail X0X0P+0X X%AX trash
+ expect_fail 0X0P+00X0P+0 %A%A trash garbage
+
+ return $RVAL
+}
+define A_floats '%A floating conversion'
+
+missing_args()
+{
+ setmsg missing_args
+
+ # Note: missing string arg is replaced by "" and behaviour
+ # of %c is either nothing or '\0' in that case, so avoid
+ # testing missing arg for %c.
+
+
+ expect '' %s
+ expect '' %b
+ expect 0 %d
+ expect 0 %o
+ expect 0 %x
+ expect 0 %#o
+ expect 0 %#X
+
+ expect 'xxxyyyzzz' '%syyy%szzz' xxx
+ expect 'a=1, b=0' 'a=%d, b=%d' 1
+
+ expect 000000 %d%u%i%x%o%X
+ expect 437000 %d%u%i%x%o%X 4 3 7
+
+ if supported f
+ then
+ expect 0.000000 %f
+ expect 'x=0.0' '%s=%.1f' x
+ fi
+
+ return $RVAL
+}
+define missing_args "format string when there are no more args"
+
+repeated_format()
+{
+ setmsg repeated_format
+
+ expect abcd %s a b c d
+ expect 1234 %d 1 2 3 4
+ expect ' 1 2 3 4' %2d 1 2 3 4
+ expect abcd %.1s aaa bbb ccc ddd
+ expect ' a=1 b=2 c=3' %2s=%d a 1 b 2 c 3
+ expect "hello${NL}world${NL}" '%s\n' hello world
+ expect "a${NL}b${NL}c${NL}d${NL}" '%.1s\n' aaa bbb ccc ddd
+
+ expect "\
+ 1.00"'
+ 9.75
+ -3.00
+ 999.99
+-101.01'"${NL}" '%7.2f\n' 1 9.75 -3 999.99 -101.01
+
+ expect " 1 010x1${NL} 220260x16${NL} 9201340x5c${NL}" \
+ '%3d%#3o%#3x\n' 1 1 1 22 22 22 92 92 92
+
+ expect ' 1 2 3 4 5' %2d 1 2 3 4 5
+ expect ' 1 2 3 4 5 0' %2d%2d%2d 1 2 3 4 5
+
+
+ return $RVAL
+}
+define repeated_format 'format string is reused until all args used'
+
+b_SysV_echo()
+{
+ setmsg b_SysV_echo
+
+ # Basic formatting
+
+ expect '' %b ''
+ expect '' %.0b abcd
+ expect abcd %b abcd
+ expect ' ab' %3.2b abcd
+ expect 'a ' %-3.1b abcd
+ expect ' ' %3.0b abcd
+
+ # The simple stuff. nb: no \c tests, it has a whole test case to itself
+
+ expect "${BSL} ${NL}" %b '\\\t\n'
+ expect '' %b '\a\v\r\f\b'
+ expect 'ABC' %b '\01A\002\0102\0003C'
+ expect "a${NL}b${NL}" %b 'a\nb\n'
+
+ # and unlikely to occur IRL
+ expect " ab" %7.4b 'ab\r\bxy\t\t\n'
+ expect "111 " %-6.3b '\00611\061\01\n\t\n'
+
+ # and last, that pesky \0
+
+ atf_require_prog wc
+ atf_require_prog sed
+
+ for fmt in '\0' '\00' '\000' '\0000'
+ do
+ if [ $( do_printf %b "${fmt}" | wc -c ) -ne 1 ]
+ then
+ atf_fail \
+ "%b '${fmt}' did not output exactly 1 character (byte)"
+ elif [ $(( $( do_printf %b "${fmt}" | od -A n -to1 ) )) -ne 0 ]
+ then
+ atf_require_prog od
+ atf_require_prog tr
+
+ RES="$(do_printf %b "${fmt}" | od -An -to1 | tr -d ' ')"
+ atf_fail \
+ "%b '${fmt}' output was '\\${RES}' should be '\\000'"
+ fi
+
+ for xt in "x${fmt}" "${fmt}q" "x${fmt}q" "${fmt}\\0" \
+ "${fmt}|\\0|\\0|" "${fmt}${fmt}" "+${fmt}-${fmt}*"
+ do
+ # nb: we "know" here that the only \'s are \0's
+ # nb: not do_printf, we are not testing ...
+ bsl=$( printf %s "${xt}" | sed -e 's/\\00*/X/g' )
+ xl=${#bsl}
+
+ RES=$(( $( do_printf %b "${xt}" | wc -c ) ))
+
+ if [ "${RES}" -ne "${xl}" ]
+ then
+ atf_fail \
+ "%b '${xt}' output ${RES} chars, expected ${xl}"
+ fi
+ done
+
+ test ${#fmt} -lt 5 && continue
+
+ if [ $( do_printf %b "${fmt}1" | wc -c ) -ne 2 ]
+ then
+ atf_fail \
+ "%b '${fmt}1' did not output exactly 2 characters"
+ fi
+ done
+
+ return $RVAL
+}
+define b_SysV_echo '%b format - emulate SysV echo escapes'
+
+b_SysV_echo_backslash_c()
+{
+ setmsg b_SysV_echo_backslash_c
+
+ # test \c in arg to printf %b .. causes instant death...
+
+ expect ab %b 'ab\cdef'
+ expect ab a%bc 'b\cd'
+
+ expect abcd %s%c%x%b a bcd 12 'd\c'
+ expect ad %.1s%x%b%c%x all 13 '\cars' cost 12
+ expect "a${NL}b" '%b\n' a 'b\c' d '\ce'
+
+ # This is undefined, though would be nice if we could rely upon it
+ # expect "abcd" %.1b 'a\c' 'b\c' 'c\c' 'd\c' '\c' e
+
+ return $RVAL
+}
+define b_SysV_echo_backslash_c 'Use of \c in arg to %b format'
+
+indirect_width()
+{
+ setmsg indirect_width
+
+ supported '*d' 5 123 || {
+ atf_skip "%*d not supported (indirect field width)"
+ return $RVAL
+ }
+
+ lpad= rpad= zpad=
+ for i in 1 2 3 4 5 6 7 8 9 10
+ do
+ expect "${lpad}7" '%*d' "$i" 7
+ expect "6${rpad}" '%-*d' "$i" 6
+ expect "${zpad}5" '%0*d' "$i" 5
+
+ lpad="${lpad} "
+ rpad="${rpad} "
+ zpad="${zpad}0"
+ done
+
+ return $RVAL
+}
+define indirect_width "using * to get field width from arg"
+
+indirect_precision()
+{
+ setmsg indirect_precision
+
+ supported '.*d' 5 123 || {
+ atf_skip "%.*d not supported (indirect precision)"
+ return $RVAL
+ }
+
+ res= zpad=.
+ for i in 0 1 2 3 4 5 6 7 8 9
+ do
+ expect "${res}" '%.*s' "$i" aaaaaaaaaaaaaaaa
+ res="${res}a"
+
+ expect "3${zpad}" '%#.*f' "$i" 3
+ zpad="${zpad}0"
+ done
+
+ return $RVAL
+}
+define indirect_precision 'Using .* as to get precision from arg'
+
+indirect_both()
+{
+ setmsg indirect_both
+
+ supported '*.*d' 5 2 123 || {
+ atf_skip "%*.*d not supported (indirect width & precision)"
+ return $RVAL
+ }
+
+ res=
+ for i in 1 2 3 4 5 6 7 8
+ do
+ res="${res}z"
+ expect " ${res}" '%*.*s' $(( $i + 2 )) "$i" zzzzzzzzzzz
+ done
+
+ expect ' ab: 9: 1.20' "%*.*s:%*d:%*.*f" 4 2 abcde 3 9 5 2 1.2
+
+ return $RVAL
+}
+define indirect_both 'Using *.* as to get width & precision from args'
+
+q_quoting()
+{
+ setmsg q_quoting
+
+ if ! supported q
+ then
+ atf_skip '%q format not supported'
+ return $RVAL
+ fi
+
+ # Testing quoting isn't as straightforward as many of the
+ # others, as there is no specific form in which the output
+ # is required to appear
+
+ # Instead, we will apply %q to various strings, and then
+ # process them again in this shell, and see if the string
+ # we get back is the same as the string we started with.
+
+ for string in \
+ abcd \
+ 'hello world' \
+ '# a comment ....' \
+ '' \
+ 'a* b* c*' \
+ 'ls | wc' \
+ '[<> # | { ~.** } $@]' \
+ '( who & echo $! )'
+ do
+ QUOTED="$(do_printf %q "$string")"
+
+ eval "RES=${QUOTED}"
+
+ if [ "${RES}" != "${string}" ]
+ then
+ atf_fail \
+ "%q <<${string}>> as <<${QUOTED}>> makes <<${RES}>>"
+ continue
+ fi
+
+ QUOTED="$(do_printf %-32q "$string")"
+
+ if [ ${#QUOTED} -lt 32 ]
+ then
+ atf-fail \
+ "%-32q <<${string}>> short result (${#QUOTED}) <<${QUOTED}>>"
+
+ fi
+
+ eval "RES=${QUOTED}"
+ if [ "${RES}" != "${string}" ]
+ then
+ atf_fail \
+ "%-32q <<${string}>> as <<${QUOTED}>> makes <<${RES}>>"
+ continue
+ fi
+ done
+
+ # %q is a variant of %s, but using field width (except as above),
+ # and especially precision makes no sense, and is implrmented so
+ # badly that testing it would be hopeless. Other flags do nothing.
+
+ return $RVAL
+}
+define q_quoting '%q quote string suitably for sh processing'
+
+NetBSD_extensions()
+{
+ setmsg NetBSD_extensions
+
+ if $BUILTIN_TEST
+ then
+ # what matters if $TEST_SH is a NetBSD sh
+ ${TEST_SH} -c 'test -n "$NETBSD_SHELL"' || {
+ atf_skip \
+ "- ${TEST_SH%% *} is not a (modern) NetBSD shell"
+ return $RVAL
+ }
+ fi
+ if ! supported '*.*%%_._' 78 66
+ then
+ if $BUILTIN_TEST
+ then
+ atf_skip \
+ "- ${TEST_SH%% *} is not a (modern enough) NetBSD shell"
+ else
+ atf_skip "- ${PRINTF} is not a (modern) NetBSD printf"
+ fi
+ return $RVAL
+ fi
+
+ # Even in the most modern NetBSD printf the data length modifiers
+ # might not be supported.
+
+ if supported zd
+ then
+ expect 88888 %jd 88888
+ expect 88888 %ld 88888
+ expect 88888 %lld 88888
+ expect 88888 %Ld 88888
+ expect 88888 %td 88888
+ expect 88888 %zd 88888
+
+ expect 23352 %hd 88888
+ expect 56 %hhd 88888
+
+ expect 300000 %jd 300000
+ expect 300000 %Ld 300000
+ expect -27680 %hd 300000
+ expect -32 %hhd 300000
+
+ expect 15b38 %jx 88888
+ expect 5b38 %hx 88888
+ expect 38 %hhx 88888
+
+ expect 93e0 %hx 300000
+ expect e0 %hhx 300000
+
+ # to test modifiers attached to floats we'd need to
+ # verify float support, so don't bother...
+ fi
+
+ # NetBSD (non-POSIX) format excape extensions
+ expect '' '\e'
+ expect '' '\E'
+ expect '' '\e\E'
+
+ # NetBSD (non-POSIX) %b string escape extensions
+ expect '' %b '\^A\^a\1'
+ expect 'S4=X' %b '\1234\75X'
+ expect 'x�z' %b 'x\M-Yz'
+ expect 'x�z' %b 'x\M^wz'
+ expect 'ab' %b 'a\^?b'
+ expect '-�-' %b '-\M^?-'
+
+ expect 'A1b2c3D4' '\x411%b\x444' '\x622\x633'
+ expect '"'\' %b\\\' '\"\e'
+ expect '+' %b '\x1+\x3'
+ expect '[1m' %b '\E[\61\x6d'
+
+ expect_fail "${BSL}" '\'
+ expect_fail '@' '\@'
+ expect_fail '%' '\%'
+ expect_fail "${BSL}" %b '\'
+ expect_fail '@' %b '\@'
+
+ # This is unspecified in posix:
+ # If arg string uses no args, but there are some, run format just once
+ expect 'hello world' 'hello world' a b c d
+
+ # Same as in format_escapes, but for \x (hex) constants
+ atf_require_prog wc
+ atf_require_prog od
+ atf_require_prog tr
+
+ for fmt in '\x0' '\x00'
+ do
+ if [ $( do_printf "${fmt}" | wc -c ) -ne 1 ]
+ then
+ atf_fail \
+ "printf '${fmt}' did not output exactly 1 character (byte)"
+ elif [ $(( $( do_printf "${fmt}" | od -A n -to1 ) )) -ne 0 ]
+ then
+
+ RES="$( do_printf "${fmt}" | od -A n -to1 | tr -d ' ')"
+ atf_fail \
+ "printf '${fmt}' output was '\\${RES}' should be '\\000'"
+ fi
+ done
+
+ # We get different results here from the builtin and command
+ # versions of printf ... OK, as which result is unspecified.
+ if $BUILTIN_TEST
+ then
+ if [ $( do_printf %c '' | wc -c ) -ne 0 ]
+ then
+ atf_require_prog sed
+
+ RES="$( do_printf %c '' |
+ od -A n -to1 |
+ sed -e 's/ [0-9]/\\&/g' -e 's/ //g' )"
+ atf_fail \
+ "printf %c '' did not output nothing: got '${RES}'"
+ fi
+ else
+ if [ $( do_printf %c '' | wc -c ) -ne 1 ]
+ then
+ atf_require_prog sed
+
+ RES="$( do_printf %c '' |
+ od -A n -to1 |
+ sed -e 's/ [0-9]/\\&/g' -e 's/ //g' )"
+ atf_fail \
+ "printf %c '' did not output nothing: got '${RES}'"
+ elif [ $(( $( do_printf %c '' | od -A n -to1 ) )) -ne 0 ]
+ then
+ RES="$( do_printf %c '' | od -A n -to1 | tr -d ' ')"
+ atf_fail \
+ "printf %c '' output was '\\${RES}' should be '\\000'"
+ fi
+ fi
+
+ return $RVAL
+}
+define NetBSD_extensions "Local NetBSD additions to printf"
+
+B_string_expand()
+{
+ setmsg B_string_expand
+
+ if ! supported B
+ then
+ atf_skip "%B format not supported"
+ return $RVAL
+ fi
+
+ # Even if %B is supported, it is not necessarily *our* %B ...
+
+ if $BUILTIN_TEST
+ then
+ # what matters if $TEST_SH is a NetBSD sh
+ ${TEST_SH} -c 'test -n "$NETBSD_SHELL"' || {
+ atf_skip \
+ "- ${TEST_SH%% *} is not a (modern) NetBSD shell"
+ return $RVAL
+ }
+ else
+ atf_require_prog uname
+
+ SYS="$(uname -s)"
+ case "${SYS}" in
+ (NetBSD) ;;
+ (*) atf_skip "- Not NetBSD (is $SYS), %B format unspecified"
+ return $RVAL
+ ;;
+ esac
+ fi
+
+ # The trivial stuff...
+ expect abcd %B abcd
+ expect ' abcd' %5B abcd
+ expect 'abcd ' %-5B abcd
+ expect ab %.2B abcd
+ expect ' ab' %5.2B abcd
+ expect 'ab ' %-5.2B abcd
+
+ # Next the semi-trivial
+ expect "abcd${BSL}n" %B "abcd${NL}"
+ expect "ab${BSL}tcd" %B "ab cd"
+ expect "${BSL}\"${BSL}e${BSL}a${BSL}b${BSL}f${BSL}r${BSL}v" \
+ %B '"'
+ expect "${BSL}'${BSL}^?" %B \'''
+ expect "${BSL}^A${BSL}^B" %B ''
+ expect "x${BSL}M-Yz" %B 'x�z'
+ expect "-${BSL}M^W-" %B '-�-'
+ expect ":${BSL}M^?:" %B ':�:'
+
+ # Then, more or less nonsense
+ expect " abcd${BSL}n" %9B "abcd${NL}"
+ expect "ab${BSL}tcd " %-9B "ab cd"
+ expect " ${BSL}'${BSL}^?" %6B \'''
+ expect "${BSL}^A${BSL}^B " %-7B ''
+ expect " -${BSL}M^W-" %8B '-�-'
+ expect ":${BSL}M^?: " %-8B ':�:'
+
+ # and finally, the absurd, ridiculous, and bizarre (useless)
+ expect "abcd${BSL}" %.5B "abcd${NL}"
+ expect "ab${BSL}" %.3B "ab cd"
+ expect "${BSL}\"${BSL}" %.3B '"'
+ expect "${BSL}" %.1B \'''
+ expect "${BSL}^" %.2B ''
+ expect "x${BSL}M-" %.4B 'x�z'
+ expect "-${BSL}M^" %.4B '-�-'
+ expect ":${BSL}M" %.3B ':�:'
+
+ return $RVAL
+}
+define B_string_expand "NetBSD specific %B string expansion"
+
+
+#############################################################################
+#############################################################################
+#
+# The code to make the tests above actually run starts here...
+#
+
+# if setup fails, then ignore any test names on command line
+# Just run the (one) test that setup() established
+setup || set --
+
+NL='
+'
+# test how the shell we're running handles quoted patterns in vars
+# Note: it is not our task here to diagnose the broken shell
+B1='\'
+B2='\\'
+case "${B1}" in
+(${B2}) BSL="${B2}";; # This one is correct
+(${B1}) BSL="${B1}";; # but some shells can't handle that
+(*) BSL=BROKEN_SHELL;; # !!!
+esac
+
+if $Running_under_ATF
+then
+ # When in ATF, just add the test cases, and finish, and ATF
+ # will take care of running everything
+
+ atf_init_test_cases() {
+
+ for T in $Tests
+ do
+ atf_add_test_case "$T"
+ done
+ return 0
+ }
+ exec 3>&2
+else
+ # When not in AFT, we need to do it all here...
+
+ Failed=
+ Failures=0
+
+ STDERR=$(mktemp ${TMPDIR:-/tmp}/Test-XXXXXX)
+ trap 'rm -f "${STDERR}"' EXIT
+ exec 3>"${STDERR}"
+
+ case "$#" in
+ (0) set -- $Tests ;;
+ esac
+
+ for T
+ do
+ $T || {
+ Failed="${Failed}${Failed:+${NL}} ${T} : "
+ eval Failed='${Failed}${TEST_'"${T}"'_MSG}'
+ Failures=$(( $Failures + 1 ))
+ }
+ done
+ if [ $Failures -gt 0 ]
+ then
+ s=s
+ test $Failures -eq 1 && s=
+
+ exec >&2
+ echo
+ echo =================================================
+ echo
+ echo "$Failures test$s failed:"
+ echo "$Failed"
+ echo
+ echo =================================================
+
+ if test -s "${STDERR}"
+ then
+ echo
+ echo The following appeared on stderr during the tests:
+ echo
+ cat "${STDERR}"
+ fi
+ fi
+fi
Index: src/tests/usr.bin/printf/t_builtin.sh
diff -u /dev/null src/tests/usr.bin/printf/t_builtin.sh:1.1
--- /dev/null Wed Sep 5 21:05:40 2018
+++ src/tests/usr.bin/printf/t_builtin.sh Wed Sep 5 21:05:40 2018
@@ -0,0 +1,123 @@
+# $NetBSD: t_builtin.sh,v 1.1 2018/09/05 21:05:40 kre Exp $
+#
+# Copyright (c) 2018 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# The shell to use for tests of the builtin printf (or at least try)
+: ${TEST_SH:=/bin/sh}
+
+# This tests the builtin printf command in ${TEST_SH}
+
+# For the actual code/tests see printf.sh
+# (shared with tests for the external (filesystem) command printf
+
+# These tests are designed to be able to be run by ATF, or standalone
+#
+# That is, either
+# atf_run t_builtin | atf-report (or whatever is needed)
+# or
+# sh t_builtin [sub_test]... (default is to run all sub_tests)
+#
+# nb: for standalone runs, do not attempt ./t_builtin as the #! line
+# added will force ATF which will complain about the test being run
+# in the wrong way. Instead use some Bourne shell compatible shell
+# (any will do, caveat any bugs it might have, it need not be TEST_SH,
+# but it can be) and run the script explicitly.
+
+do_printf()
+{
+ $Running_under_ATF && atf_require_prog "${TEST_SH%% *}"
+
+ unset LANG LC_ALL LC_NUMERIC LC_CTYPE LC_MESSAGES
+
+ case "$*" in
+ *\'*)
+ $Running_under_ATF && atf_require_prog printf
+ $Running_under_ATF && atf_require_pfog sed
+ ;;
+ esac
+
+ COMMAND=printf
+ for ARG
+ do
+ case "${ARG}" in
+ (*\'*)
+ # This is kind of odd, we need a working
+ # printf in order to test printf ...
+ # nb: do not use echo here, an arg might be "-n'x"
+ COMMAND="${COMMAND} '$(
+ printf '%s\n' "${ARG}" |
+ sed "s/'/'\\\\''/g"
+ )'"
+ ;;
+ (*)
+ COMMAND="${COMMAND} '${ARG}'"
+ ;;
+ esac
+ done
+ ${TEST_SH} -c "${COMMAND}"
+}
+
+Not_builtin()
+{
+ if $Running_under_ATF
+ then
+ atf_skip "${TEST_SH%% *} does not have printf built in"
+ else
+ echo >&2 "No builtin printf in ${TEST_SH}"
+ exit 1
+ fi
+}
+
+# See if we have a builtin "printf" command to test
+
+setup()
+{
+ case "$( ${TEST_SH} -c 'type printf' 2>&1 )" in
+
+ ( *[Bb]uiltin* | *[Bb]uilt[-\ ][Ii]n* )
+ # nothing here, it all happens below.
+ ;;
+
+ (*) Tests=
+ define Not_builtin 'Dummy test to skip when no printf builtin'
+ return 1
+ ;;
+ esac
+
+ return 0
+}
+
+setmsg()
+{
+ MSG="${TEST_SH%% *} builtin printf"
+ CurrentTest="$1"
+ RVAL=0
+}
+
+BUILTIN_TEST=true
+
+# All the code to actually run the test comes from printf.sh ...
+
Index: src/tests/usr.bin/printf/t_command.sh
diff -u /dev/null src/tests/usr.bin/printf/t_command.sh:1.1
--- /dev/null Wed Sep 5 21:05:40 2018
+++ src/tests/usr.bin/printf/t_command.sh Wed Sep 5 21:05:40 2018
@@ -0,0 +1,144 @@
+# $NetBSD: t_command.sh,v 1.1 2018/09/05 21:05:40 kre Exp $
+#
+# Copyright (c) 2018 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# The printf command to test (if not a full path, $PATH will be examined)
+# Do not use relative (./ or ../) paths when running under ATF.
+: ${TEST_PRINTF:=/usr/bin/printf}
+
+# This tests an external (filesystem) printf command
+
+# For the actual code/tests see printf.sh
+# (shared with tests for the shell builtin printf
+
+# These tests are designed to be able to be run by ATF, or standalone
+#
+# That is, either
+# atf_run t_command | atf-report (or whatever is needed)
+# or
+# sh t_command [sub_test]... ( default is to run all sub_tests )
+#
+# nb: for standalone runs, do not attempt ./t_builtin as the #! line
+# added will force ATF which will complain about the incorrect method
+# of running the test. Instead use some Bourne shell compatible shell
+# (any will do, caveat any bugs it might have), and run the script explicitly.
+
+do_printf()
+{
+ $Running_under_ATF && atf_require_prog "${PRINTF%% *}"
+
+ unset LANG LC_ALL LC_NUMERIC LC_CTYPE LC_MESSAGES
+
+ ${PRINTF} "$@"
+}
+
+No_command()
+{
+ setmsg No_command
+
+ case "${TEST_PRINTF%% *}" in
+ ( '' )
+ msg='Configuration error: check $TEST_PRINTF'
+ ;;
+ ( /* | ./* | ../* )
+ msg="Cannot find/execute ${TEST_PRINTF%% *}"
+ ;;
+ ( * )
+ msg="No '${TEST_PRINTF%% *}' found in "'$PATH'
+ ;;
+ esac
+ atf_skip "${msg}"
+
+ return $RVAL
+}
+
+# See if we have a "printf" command in $PATH to test - pick the first
+
+setup()
+{
+ saveIFS="${IFS-UnSet}"
+ saveOPTS="$(set +o)"
+
+ unset PRINTF
+
+ case "${TEST_PRINTF%% *}" in
+ ( /* ) PRINTF="${TEST_PRINTF}" ;;
+ ( ./* | ../* ) PRINTF="${PWD}/${TEST_PRINTF}" ;;
+ (*)
+ set -f
+ IFS=:
+ for P in $PATH
+ do
+ case "$P" in
+ ('' | . ) D="${PWD}";;
+ ( /* ) D="${P}" ;;
+ ( * ) D="${PWD}/${P}";;
+ esac
+
+ test -x "${D}/${TEST_PRINTF%% *}" || continue
+
+ PRINTF="${D}/${TEST_PRINTF}"
+ break
+ done
+ unset IFS
+ eval "${saveOPTS}"
+
+ case "${saveIFS}" in
+ (UnSet) unset IFS;;
+ (*) IFS="${saveIFS}";;
+ esac
+ ;;
+ esac
+
+ test -x "${PRINTF%% *}" || PRINTF=
+
+ case "${PRINTF}" in
+
+ ('') Tests=
+ define No_command 'Dummy test to skip no printf command'
+ return 1
+ ;;
+
+ ( * )
+ # nothing here, it all happens below.
+ ;;
+
+ esac
+
+ return 0
+}
+
+setmsg()
+{
+ MSG="${PRINTF}"
+ CurrentTest="$1"
+ RVAL=0
+}
+
+BUILTIN_TEST=false
+
+# All the code to actually run the test comes from printf.sh ...
+