Module Name: src Committed By: christos Date: Tue Mar 8 14:26:54 UTC 2016
Modified Files: src/tests/bin/sh: t_expand.sh t_fsplit.sh t_redir.sh Log Message: Added more test cases, more exhaustive testing. (from kre) To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/tests/bin/sh/t_expand.sh cvs rdiff -u -r1.1 -r1.2 src/tests/bin/sh/t_fsplit.sh cvs rdiff -u -r1.3 -r1.4 src/tests/bin/sh/t_redir.sh Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/bin/sh/t_expand.sh diff -u src/tests/bin/sh/t_expand.sh:1.5 src/tests/bin/sh/t_expand.sh:1.6 --- src/tests/bin/sh/t_expand.sh:1.5 Mon Feb 22 15:02:29 2016 +++ src/tests/bin/sh/t_expand.sh Tue Mar 8 09:26:54 2016 @@ -1,4 +1,4 @@ -# $NetBSD: t_expand.sh,v 1.5 2016/02/22 20:02:29 christos Exp $ +# $NetBSD: t_expand.sh,v 1.6 2016/03/08 14:26:54 christos Exp $ # # Copyright (c) 2007, 2009 The NetBSD Foundation, Inc. # All rights reserved. @@ -24,6 +24,8 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # +# the implementation of "sh" to test +: ${TEST_SH:="/bin/sh"} # # This file tests the functions in expand.c. @@ -50,19 +52,15 @@ dollar_at_head() { } dollar_at_body() { # This one should work everywhere. - got=`echo "" "" | sed 's,$,EOL,'` - atf_check_equal ' EOL' '$got' + atf_check -s exit:0 -o inline:' EOL\n' -e empty \ + ${TEST_SH} -c 'echo "" "" | '" sed 's,\$,EOL,'" # This code triggered the bug. - set -- "" "" - got=`echo "$@" | sed 's,$,EOL,'` - atf_check_equal ' EOL' '$got' - - set -- - - shift - n_arg() { echo $#; } - n_args=`n_arg "$@"` - atf_check_equal '0' '$n_args' + atf_check -s exit:0 -o inline:' EOL\n' -e empty \ + ${TEST_SH} -c 'set -- "" ""; echo "$@" | '" sed 's,\$,EOL,'" + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'set -- -; shift; n_arg() { echo $#; }; n_arg "$@"' } atf_test_case dollar_at_with_text @@ -71,27 +69,91 @@ dollar_at_with_text_head() { "within the quotes. PR bin/33956." } dollar_at_with_text_body() { - set -- - atf_check_equal '' "$(delim_argv "$@")" - atf_check_equal '>foobar<' "$(delim_argv "foo$@bar")" - atf_check_equal '>foo bar<' "$(delim_argv "foo $@ bar")" - - set -- a b c - atf_check_equal '>a< >b< >c<' "$(delim_argv "$@")" - atf_check_equal '>fooa< >b< >cbar<' "$(delim_argv "foo$@bar")" - atf_check_equal '>foo a< >b< >c bar<' "$(delim_argv "foo $@ bar")" + + cat <<'EOF' > h-f1 + +delim_argv() { + str= + while [ $# -gt 0 ]; do + if [ -z "${str}" ]; then + str=">$1<" + else + str="${str} >$1<" + fi + shift + done + echo "${str}" +} + +EOF + cat <<'EOF' > h-f2 + +delim_argv() { + str= + while [ $# -gt 0 ]; do + + str="${str}${str:+ }>$1<" + shift + + done + echo "${str}" +} + +EOF + + chmod +x h-f1 h-f2 + + for f in 1 2 + do + atf_check -s exit:0 -o inline:'\n' -e empty ${TEST_SH} -c \ + ". ./h-f${f}; "'set -- ; delim_argv "$@"' + atf_check -s exit:0 -o inline:'>foobar<\n' -e empty \ + ${TEST_SH} -c \ + ". ./h-f${f}; "'set -- ; delim_argv "foo$@bar"' + atf_check -s exit:0 -o inline:'>foo bar<\n' -e empty \ + ${TEST_SH} -c \ + ". ./h-f${f}; "'set -- ; delim_argv "foo $@ bar"' + + atf_check -s exit:0 -o inline:'>a< >b< >c<\n' -e empty \ + ${TEST_SH} -c \ + ". ./h-f${f}; "'set -- a b c; delim_argv "$@"' + atf_check -s exit:0 -o inline:'>fooa< >b< >cbar<\n' -e empty \ + ${TEST_SH} -c \ + ". ./h-f${f}; "'set -- a b c; delim_argv "foo$@bar"' + atf_check -s exit:0 -o inline:'>foo a< >b< >c bar<\n' -e empty \ + ${TEST_SH} -c \ + ". ./h-f${f}; "'set -- a b c; delim_argv "foo $@ bar"' + done } atf_test_case strip strip_head() { atf_set "descr" "Checks that the %% operator works and strips" \ "the contents of a variable from the given point" \ - "to the end (PR bin/43469)" + "to the end" } strip_body() { line='#define bindir "/usr/bin" /* comment */' stripped='#define bindir "/usr/bin" ' - atf_check_equal '$stripped' '${line%%/\**}' + + # atf_expect_fail "PR bin/43469" -- now fixed + for exp in \ + '${line%%/\**}' \ + '${line%%"/*"*}' \ + '${line%%'"'"'/*'"'"'*}' \ + '"${line%%/\**}"' \ + '"${line%%"/*"*}"' \ + '"${line%%'"'"'/*'"'"'*}"' \ + '${line%/\**}' \ + '${line%"/*"*}' \ + '${line%'"'"'/*'"'"'*}' \ + '"${line%/\**}"' \ + '"${line%"/*"*}"' \ + '"${line%'"'"'/*'"'"'*}"' + do + atf_check -o inline:":$stripped:\n" -e empty ${TEST_SH} -c \ + "line='${line}'; echo :${exp}:" + done } atf_test_case varpattern_backslashes @@ -102,7 +164,8 @@ varpattern_backslashes_head() { varpattern_backslashes_body() { line='/foo/bar/*/baz' stripped='/foo/bar/' - atf_check_equal $stripped ${line%%\**} + atf_check -o inline:'/foo/bar/\n' -e empty ${TEST_SH} -c \ + 'line="/foo/bar/*/baz"; echo ${line%%\**}' } atf_test_case arithmetic @@ -113,9 +176,13 @@ arithmetic_head() { "this is true." } arithmetic_body() { - atf_check_equal '3' '$((1 + 2))' - atf_check_equal '2147483647' '$((0x7fffffff))' - atf_check_equal '9223372036854775807' '$(((1 << 63) - 1))' + + atf_check -o inline:'3' -e empty ${TEST_SH} -c \ + 'printf %s $((1 + 2))' + atf_check -o inline:'2147483647' -e empty ${TEST_SH} -c \ + 'printf %s $((0x7fffffff))' + atf_check -o inline:'9223372036854775807' -e empty ${TEST_SH} -c \ + 'printf %s $(((1 << 63) - 1))' } atf_test_case iteration_on_null_parameter @@ -125,10 +192,39 @@ iteration_on_null_parameter_head() { "PR bin/48202." } iteration_on_null_parameter_body() { - s1=`/bin/sh -uc 'N=; set -- ${N}; for X; do echo "[$X]"; done' 2>&1` - s2=`/bin/sh -uc 'N=; set -- ${N:-}; for X; do echo "[$X]"; done' 2>&1` - atf_check_equal '' '$s1' - atf_check_equal '[]' '$s2' + atf_check -o empty -e empty ${TEST_SH} -c \ + 'N=; set -- ${N}; for X; do echo "[$X]"; done' +} + +atf_test_case iteration_on_quoted_null_parameter +iteration_on_quoted_null_parameter_head() { + atf_set "descr" \ + 'Check iteration of "$@" in for loop when set to null;' +} +iteration_on_quoted_null_parameter_body() { + atf_check -o inline:'[]\n' -e empty ${TEST_SH} -c \ + 'N=; set -- "${N}"; for X; do echo "[$X]"; done' +} + +atf_test_case iteration_on_null_or_null_parameter +iteration_on_null_or_null_parameter_head() { + atf_set "descr" \ + 'Check expansion of null parameter as default for another null' +} +iteration_on_null_or_null_parameter_body() { + atf_check -o empty -e empty ${TEST_SH} -c \ + 'N=; E=; set -- ${N:-${E}}; for X; do echo "[$X]"; done' +} + +atf_test_case iteration_on_null_or_missing_parameter +iteration_on_null_or_missing_parameter_head() { + atf_set "descr" \ + 'Check expansion of missing parameter as default for another null' +} +iteration_on_null_or_missing_parameter_body() { + # atf_expect_fail 'PR bin/50834' + atf_check -o empty -e empty ${TEST_SH} -c \ + 'N=; set -- ${N:-}; for X; do echo "[$X]"; done' } atf_init_test_cases() { @@ -138,4 +234,7 @@ atf_init_test_cases() { atf_add_test_case varpattern_backslashes atf_add_test_case arithmetic atf_add_test_case iteration_on_null_parameter + atf_add_test_case iteration_on_quoted_null_parameter + atf_add_test_case iteration_on_null_or_null_parameter + atf_add_test_case iteration_on_null_or_missing_parameter } Index: src/tests/bin/sh/t_fsplit.sh diff -u src/tests/bin/sh/t_fsplit.sh:1.1 src/tests/bin/sh/t_fsplit.sh:1.2 --- src/tests/bin/sh/t_fsplit.sh:1.1 Sat Mar 17 12:33:11 2012 +++ src/tests/bin/sh/t_fsplit.sh Tue Mar 8 09:26:54 2016 @@ -1,6 +1,6 @@ -# $NetBSD: t_fsplit.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $ +# $NetBSD: t_fsplit.sh,v 1.2 2016/03/08 14:26:54 christos Exp $ # -# Copyright (c) 2007 The NetBSD Foundation, Inc. +# Copyright (c) 2007-2016 The NetBSD Foundation, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ # the "${x-" and "}" were absent from the input line. # # So: sh -c 'set ${x-a b c}; echo $#' should give 3. +# and: sh -c 'set -- ${x-}' echo $#' shold give 0 # nl=' @@ -40,15 +41,40 @@ nl=' check() { - result="$(eval $1)" + TEST=$((${TEST} + 1)) + + case "$#" in + (2) ;; + (*) atf_fail "Internal test error, $# args to check test ${TEST}";; + esac + + result=$( ${TEST_SH} -c "unset x; $1" ) + STATUS="$?" + # Remove newlines oifs="$IFS" IFS="$nl" result="$(echo $result)" IFS="$oifs" + + # trim the test text in case we use it in a message below + case "$1" in + ????????????????*) + set -- "$(expr "$1" : '\(............\).*')..." "$2" ;; + esac + if [ "$2" != "$result" ] then - atf_fail "expected [$2], found [$result]" + if [ "${STATUS}" = "0" ] + then + atf_fail "Test ${TEST} '$1': expected [$2], found [$result]" + else + atf_fail \ + "TEST ${TEST} '$1' failed ($STATUS): expected [$2], found [$result]" + fi + elif [ "${STATUS}" != 0 ] + then + atf_fail "TEST ${TEST} '$1' failed ($STATUS)" fi } @@ -59,6 +85,7 @@ for_head() { for_body() { unset x + TEST=0 # Since I managed to break this, leave the test in check 'for f in $x; do echo x${f}y; done' '' } @@ -68,17 +95,121 @@ default_val_head() { atf_set "descr" "Checks field splitting in variable default values" } default_val_body() { - unset x - + TEST=0 # Check that IFS is applied to text from ${x-...} unless it is inside # any set of "..." - check 'set ${x-a b c}; echo $#' 3 - check 'for i in ${x-a b c}; do echo "z${i}z"; done' 'zaz zbz zcz' - check 'for i in ${x-"a b" c}; do echo "z${i}z"; done' 'za bz zcz' - check 'for i in ${x-"a ${x-b c}" d}; do echo "z${i}z"; done' 'za b cz zdz' - check 'for i in ${x-"a ${x-"b c"}" d}; do echo "z${i}z"; done' 'za b cz zdz' - check 'for i in ${x-a ${x-"b c"} d}; do echo "z${i}z"; done' 'zaz zb cz zdz' - check 'for i in ${x-a ${x-b c} d}; do echo "z${i}z"; done' 'zaz zbz zcz zdz' + check 'set -- ${x-a b c}; echo $#' 3 + + check 'set -- ${x-"a b" c}; echo $#' 2 + check 'set -- ${x-a "b c"}; echo $#' 2 + check 'set -- ${x-"a b c"}; echo $#' 1 + + check "set -- \${x-'a b' c}; echo \$#" 2 + check "set -- \${x-a 'b c'}; echo \$#" 2 + check "set -- \${x-'a b c'}; echo \$#" 1 + + check 'set -- ${x-a\ b c}; echo $#' 2 + check 'set -- ${x-a b\ c}; echo $#' 2 + check 'set -- ${x-a\ b\ c}; echo $#' 1 + + check 'set -- ${x}; echo $#' 0 + check 'set -- ${x-}; echo $#' 0 + check 'set -- ${x-""}; echo $#' 1 + check 'set -- ""${x}; echo $#' 1 + check 'set -- ""${x-}; echo $#' 1 + check 'set -- ""${x-""}; echo $#' 1 + check 'set -- ${x}""; echo $#' 1 + check 'set -- ${x-}""; echo $#' 1 + check 'set -- ${x-""}""; echo $#' 1 + check 'set -- ""${x}""; echo $#' 1 + check 'set -- ""${x-}""; echo $#' 1 + check 'set -- ""${x-""}""; echo $#' 1 + + check 'for i in ${x-a b c}; do echo "z${i}z"; done' \ + 'zaz zbz zcz' + check 'for i in ${x-"a b" c}; do echo "z${i}z"; done' \ + 'za bz zcz' + check 'for i in ${x-"a ${x-b c}" d}; do echo "z${i}z"; done' \ + 'za b cz zdz' + check 'for i in ${x-a ${x-b c} d}; do echo "z${i}z"; done' \ + 'zaz zbz zcz zdz' + + # I am not sure these two are correct, the rules on quoting word + # in ${var-word} are peculiar, and hard to fathom... + # They are what the NetBSD shell does, and bash, not the freebsd shell + # (as of Mar 1, 2016) + + check 'for i in ${x-"a ${x-"b c"}" d}; do echo "z${i}z"; done' \ + 'za b cz zdz' + check 'for i in ${x-a ${x-"b c"} d}; do echo "z${i}z"; done' \ + 'zaz zb cz zdz' +} + +atf_test_case replacement_val +replacement_val_head() { + atf_set "descr" "Checks field splitting in variable replacement values" +} +replacement_val_body() { + TEST=0 + + # Check that IFS is applied to text from ${x+...} unless it is inside + # any set of "...", or whole expansion is quoted, or both... + + check 'x=BOGUS; set -- ${x+a b c}; echo $#' 3 + + check 'x=BOGUS; set -- ${x+"a b" c}; echo $#' 2 + check 'x=BOGUS; set -- ${x+a "b c"}; echo $#' 2 + check 'x=BOGUS; set -- ${x+"a b c"}; echo $#' 1 + + check "x=BOGUS; set -- \${x+'a b' c}; echo \$#" 2 + check "x=BOGUS; set -- \${x+a 'b c'}; echo \$#" 2 + check "x=BOGUS; set -- \${x+'a b c'}; echo \$#" 1 + + check 'x=BOGUS; set -- ${x+a\ b c}; echo $#' 2 + check 'x=BOGUS; set -- ${x+a b\ c}; echo $#' 2 + check 'x=BOGUS; set -- ${x+a\ b\ c}; echo $#' 1 + + check 'x=BOGUS; set -- ${x+}; echo $#' 0 + check 'x=BOGUS; set -- ${x+""}; echo $#' 1 + check 'x=BOGUS; set -- ""${x+}; echo $#' 1 + check 'x=BOGUS; set -- ""${x+""}; echo $#' 1 + check 'x=BOGUS; set -- ${x+}""; echo $#' 1 + check 'x=BOGUS; set -- ${x+""}""; echo $#' 1 + check 'x=BOGUS; set -- ""${x+}""; echo $#' 1 + check 'x=BOGUS; set -- ""${x+""}""; echo $#' 1 + + # verify that the value of $x does not affecty the value of ${x+...} + check 'x=BOGUS; set -- ${x+}; echo X$1' X + check 'x=BOGUS; set -- ${x+""}; echo X$1' X + check 'x=BOGUS; set -- ""${x+}; echo X$1' X + check 'x=BOGUS; set -- ""${x+""}; echo X$1' X + check 'x=BOGUS; set -- ${x+}""; echo X$1' X + check 'x=BOGUS; set -- ${x+""}""; echo X$1' X + check 'x=BOGUS; set -- ""${x+}""; echo X$1' X + check 'x=BOGUS; set -- ""${x+""}""; echo X$1' X + + check 'x=BOGUS; set -- ${x+}; echo X${1-:}X' X:X + check 'x=BOGUS; set -- ${x+""}; echo X${1-:}X' XX + check 'x=BOGUS; set -- ""${x+}; echo X${1-:}X' XX + check 'x=BOGUS; set -- ""${x+""}; echo X${1-:}X' XX + check 'x=BOGUS; set -- ${x+}""; echo X${1-:}X' XX + check 'x=BOGUS; set -- ${x+""}""; echo X${1-:}X' XX + check 'x=BOGUS; set -- ""${x+}""; echo X${1-:}X' XX + check 'x=BOGUS; set -- ""${x+""}""; echo X${1-:}X' XX + + # and validate that the replacement can be used as expected + check 'x=BOGUS; for i in ${x+a b c}; do echo "z${i}z"; done'\ + 'zaz zbz zcz' + check 'x=BOGUS; for i in ${x+"a b" c}; do echo "z${i}z"; done'\ + 'za bz zcz' + check 'x=BOGUS; for i in ${x+"a ${x+b c}" d}; do echo "z${i}z"; done'\ + 'za b cz zdz' + check 'x=BOGUS; for i in ${x+"a ${x+"b c"}" d}; do echo "z${i}z"; done'\ + 'za b cz zdz' + check 'x=BOGUS; for i in ${x+a ${x+"b c"} d}; do echo "z${i}z"; done'\ + 'zaz zb cz zdz' + check 'x=BOGUS; for i in ${x+a ${x+b c} d}; do echo "z${i}z"; done'\ + 'zaz zbz zcz zdz' } atf_test_case ifs_alpha @@ -89,13 +220,19 @@ ifs_alpha_head() { ifs_alpha_body() { unset x + TEST=0 # repeat with an alphabetic in IFS check 'IFS=q; set ${x-aqbqc}; echo $#' 3 - check 'IFS=q; for i in ${x-aqbqc}; do echo "z${i}z"; done' 'zaz zbz zcz' - check 'IFS=q; for i in ${x-"aqb"qc}; do echo "z${i}z"; done' 'zaqbz zcz' - check 'IFS=q; for i in ${x-"aq${x-bqc}"qd}; do echo "z${i}z"; done' 'zaqbqcz zdz' - check 'IFS=q; for i in ${x-"aq${x-"bqc"}"qd}; do echo "z${i}z"; done' 'zaqbqcz zdz' - check 'IFS=q; for i in ${x-aq${x-"bqc"}qd}; do echo "z${i}z"; done' 'zaz zbqcz zdz' + check 'IFS=q; for i in ${x-aqbqc}; do echo "z${i}z"; done' \ + 'zaz zbz zcz' + check 'IFS=q; for i in ${x-"aqb"qc}; do echo "z${i}z"; done' \ + 'zaqbz zcz' + check 'IFS=q; for i in ${x-"aq${x-bqc}"qd}; do echo "z${i}z"; done' \ + 'zaqbqcz zdz' + check 'IFS=q; for i in ${x-"aq${x-"bqc"}"qd}; do echo "z${i}z"; done' \ + 'zaqbqcz zdz' + check 'IFS=q; for i in ${x-aq${x-"bqc"}qd}; do echo "z${i}z"; done' \ + 'zaz zbqcz zdz' } atf_test_case quote @@ -106,6 +243,7 @@ quote_head() { quote_body() { unset x + TEST=0 # Some quote propagation checks check 'set "${x-a b c}"; echo $#' 1 check 'set "${x-"a b" c}"; echo $1' 'a b c' @@ -120,19 +258,39 @@ dollar_at_head() { dollar_at_body() { unset x + TEST=0 # Check we get "$@" right - check 'set ""; for i; do echo "z${i}z"; done' 'zz' - check 'set ""; for i in "$@"; do echo "z${i}z"; done' 'zz' - check 'set "" ""; for i; do echo "z${i}z"; done' 'zz zz' - check 'set "" ""; for i in "$@"; do echo "z${i}z"; done' 'zz zz' - check 'set "" ""; for i in $@; do echo "z${i}z"; done' '' - check 'set "a b" c; for i; do echo "z${i}z"; done' 'za bz zcz' - check 'set "a b" c; for i in "$@"; do echo "z${i}z"; done' 'za bz zcz' - check 'set "a b" c; for i in $@; do echo "z${i}z"; done' 'zaz zbz zcz' - check 'set " a b " c; for i in "$@"; do echo "z${i}z"; done' 'z a b z zcz' - check 'set --; for i in x"$@"x; do echo "z${i}z"; done' 'zxxz' - check 'set a; for i in x"$@"x; do echo "z${i}z"; done' 'zxaxz' - check 'set a b; for i in x"$@"x; do echo "z${i}z"; done' 'zxaz zbxz' + + check 'set --; for i in x"$@"x; do echo "z${i}z"; done' 'zxxz' + check 'set a; for i in x"$@"x; do echo "z${i}z"; done' 'zxaxz' + check 'set a b; for i in x"$@"x; do echo "z${i}z"; done' 'zxaz zbxz' + + check 'set --; for i; do echo "z${i}z"; done' '' + check 'set --; for i in $@; do echo "z${i}z"; done' '' + check 'set --; for i in "$@"; do echo "z${i}z"; done' '' + # atf_expect_fail "PR bin/50834" + check 'set --; for i in ""$@; do echo "z${i}z"; done' 'zz' + # atf_expect_pass + check 'set --; for i in $@""; do echo "z${i}z"; done' 'zz' + check 'set --; for i in ""$@""; do echo "z${i}z"; done' 'zz' + check 'set --; for i in """$@"; do echo "z${i}z"; done' 'zz' + check 'set --; for i in "$@"""; do echo "z${i}z"; done' 'zz' + check 'set --; for i in """$@""";do echo "z${i}z"; done' 'zz' + + check 'set ""; for i; do echo "z${i}z"; done' 'zz' + check 'set ""; for i in "$@"; do echo "z${i}z"; done' 'zz' + check 'set "" ""; for i; do echo "z${i}z"; done' 'zz zz' + check 'set "" ""; for i in "$@"; do echo "z${i}z"; done' 'zz zz' + check 'set "" ""; for i in $@; do echo "z${i}z"; done' '' + + check 'set "a b" c; for i; do echo "z${i}z"; done' \ + 'za bz zcz' + check 'set "a b" c; for i in "$@"; do echo "z${i}z"; done' \ + 'za bz zcz' + check 'set "a b" c; for i in $@; do echo "z${i}z"; done' \ + 'zaz zbz zcz' + check 'set " a b " c; for i in "$@"; do echo "z${i}z"; done' \ + 'z a b z zcz' } atf_test_case ifs @@ -143,6 +301,7 @@ ifs_head() { ifs_body() { unset x + TEST=0 # Some IFS tests check 't="-- "; IFS=" "; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '0' check 't=" x"; IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1' @@ -165,19 +324,26 @@ var_length_head() { "a variable's length" } var_length_body() { - unset x + TEST=0 - # Check that we apply IFS to ${#var} long=12345678123456781234567812345678 long=$long$long$long$long - check 'echo ${#long}; IFS=2; echo ${#long}; set 1 ${#long};echo $#' '128 1 8 3' - check 'IFS=2; set ${x-${#long}}; IFS=" "; echo $* $#' '1 8 2' - check 'IFS=2; set ${x-"${#long}"}; IFS=" "; echo $* $#' '128 1' + export long + + # first test that the test method works... + check 'set -u; : ${long}; echo ${#long}' '128' + + # Check that we apply IFS to ${#var} + check 'echo ${#long}; IFS=2; echo ${#long}; set 1 ${#long};echo $#' \ + '128 1 8 3' + check 'IFS=2; set ${x-${#long}}; IFS=" "; echo $* $#' '1 8 2' + check 'IFS=2; set ${x-"${#long}"}; IFS=" "; echo $* $#' '128 1' } atf_init_test_cases() { atf_add_test_case for atf_add_test_case default_val + atf_add_test_case replacement_val atf_add_test_case ifs_alpha atf_add_test_case quote atf_add_test_case dollar_at Index: src/tests/bin/sh/t_redir.sh diff -u src/tests/bin/sh/t_redir.sh:1.3 src/tests/bin/sh/t_redir.sh:1.4 --- src/tests/bin/sh/t_redir.sh:1.3 Tue Mar 1 07:39:35 2016 +++ src/tests/bin/sh/t_redir.sh Tue Mar 8 09:26:54 2016 @@ -1,4 +1,4 @@ -# $NetBSD: t_redir.sh,v 1.3 2016/03/01 12:39:35 christos Exp $ +# $NetBSD: t_redir.sh,v 1.4 2016/03/08 14:26:54 christos Exp $ # # Copyright (c) 2016 The NetBSD Foundation, Inc. # All rights reserved. @@ -27,32 +27,440 @@ # the implementation of "sh" to test : ${TEST_SH:="/bin/sh"} +# Any failures in this first test means it is not worth bothering looking +# for causes of failures in any other tests, make this one work first. + +# Problems with this test usually mean inadequate ATF_SHELL used for testing. +# (though if all pass but the last, it might be a TEST_SH problem.) + +atf_test_case basic_test_method_test +basic_test_method_test_head() +{ + atf_set "descr" "Tests that test method works as expected" +} +basic_test_method_test_body() +{ + cat <<- 'DONE' | + DONE + atf_check -s exit:0 -o empty -e empty ${TEST_SH} + cat <<- 'DONE' | + DONE + atf_check -s exit:0 -o match:0 -e empty ${TEST_SH} -c 'wc -l' + + cat <<- 'DONE' | + echo hello + DONE + atf_check -s exit:0 -o match:hello -e empty ${TEST_SH} + cat <<- 'DONE' | + echo hello + DONE + atf_check -s exit:0 -o match:1 -e empty ${TEST_SH} -c 'wc -l' + + cat <<- 'DONE' | + echo hello\ + world + DONE + atf_check -s exit:0 -o match:helloworld -e empty ${TEST_SH} + cat <<- 'DONE' | + echo hello\ + world + DONE + atf_check -s exit:0 -o match:2 -e empty ${TEST_SH} -c 'wc -l' + + printf '%s\n%s\n%s\n' Line1 Line2 Line3 > File + atf_check -s exit:0 -o inline:'Line1\nLine2\nLine3\n' -e empty \ + ${TEST_SH} -c 'cat File' + + cat <<- 'DONE' | + set -- X "" '' Y + echo ARGS="${#}" + echo '' -$1- -$2- -$3- -$4- + cat <<EOF + X=$1 + EOF + cat <<\EOF + Y=$4 + EOF + DONE + atf_check -s exit:0 -o match:ARGS=4 -o match:'-X- -- -- -Y-' \ + -o match:X=X -o match:'Y=\$4' -e empty ${TEST_SH} +} + +atf_test_case do_input_redirections +do_input_redirections_head() +{ + atf_set "descr" "Tests that simple input redirection works" +} +do_input_redirections_body() +{ + printf '%s\n%s\n%s\nEND\n' 'First Line' 'Second Line' 'Line 3' >File + + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} -c 'cat < File' + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} -c 'cat <File' + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} -c 'cat< File' + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} -c 'cat < "File"' + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} -c '< File cat' + + ln File wc + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} -c '< wc cat' + + mv wc cat + atf_check -s exit:0 -e empty -o match:4 \ + ${TEST_SH} -c '< cat wc' + + + cat <<- 'EOF' | + i=0 + while [ "$i" -lt 3 ]; do + i=$((i + 1)) + read line < File + echo "$line" + done + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nFirst Line\nFirst Line\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + i=0 + while [ "$i" -lt 3 ]; do + i=$((i + 1)) + read line + echo "$line" + done <File + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + i=0 + while [ "$i" -lt 3 ]; do + i=$((i + 1)) + read line < File + echo "$line" + done <File + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nFirst Line\nFirst Line\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + line= + while [ "$line" != END ]; do + read line || exit 1 + echo "$line" + done <File + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + while :; do + read line || exit 0 + echo "$line" + done <File + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + i=0 + while read line < File + do + echo "$line" + i=$((i + 1)) + [ ${i} -ge 3 ] && break + done + echo DONE + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nFirst Line\nFirst Line\nDONE\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + i=0 + while read line + do + echo "$line" + done <File + echo DONE + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nEND\nDONE\n' \ + ${TEST_SH} + + cat <<- 'EOF' | + i=0 + while read line + do + echo "$line" + i=$((i + 1)) + [ ${i} -ge 3 ] && break + done <File + echo DONE + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line\nSecond Line\nLine 3\nDONE\n' ${TEST_SH} + + cat <<- 'EOF' | + i=0 + while read line1 <File + do + read line2 + echo "$line1":"$line2" + i=$((i + 1)) + [ ${i} -ge 2 ] && break + done <File + echo DONE + EOF + atf_check -s exit:0 -e empty \ + -o inline:'First Line:First Line\nFirst Line:Second Line\nDONE\n' \ + ${TEST_SH} +} + +atf_test_case do_output_redirections +do_output_redirections_head() +{ + atf_set "descr" "Test Output redirections" +} +do_output_redirections_body() +{ +nl=' +' + T=0 + i() { T=$(($T + 1)); } + + rm -f Output 2>/dev/null || : + test -f Output && atf_fail "Unable to remove Output file" +#1 + i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '> Output' + test -f Output || atf_fail "#$T: Did not make Output file" +#2 + rm -f Output 2>/dev/null || : + i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>> Output' + test -f Output || atf_fail "#$T: Did not make Output file" +#3 + rm -f Output 2>/dev/null || : + i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>| Output' + test -f Output || atf_fail "#$T: Did not make Output file" + +#4 + rm -f Output 2>/dev/null || : + i + atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello >Output' + test -s Output || atf_fail "#$T: Did not make non-empty Output file" + test "$(cat Output)" = "Hello" || + atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'" +#5 + i + atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello>!Output' + test -s Output || atf_fail "#$T: Did not make non-empty Output file" + test "$(cat Output)" = "Hello" || + atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'" +#6 + i + atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Bye >>Output' + test -s Output || atf_fail "#$T: Removed Output file" + test "$(cat Output)" = "Hello${nl}Bye" || atf_fail \ + "#$T: Incorrect Output: Should be 'Hello\\nBye' is '$(cat Output)'" +#7 + i; atf_check -s exit:0 -o inline:'line 1\nline 2\n' -e empty \ + ${TEST_SH} -c \ + 'echo line 1 > Output; echo line 2 >> Output; cat Output' + test "$(cat Output)" = "line 1${nl}line 2" || atf_fail \ + "#$T: Incorrect Output: Should be 'line 1\\nline 2' is '$(cat Output)'" +#8 + i; atf_check -s exit:0 -o inline:'line 2\n' -e empty \ + ${TEST_SH} -c 'echo line 1 > Output; echo line 2' + test "$(cat Output)" = "line 1" || atf_fail \ + "#$T: Incorrect Output: Should be 'line 1' is '$(cat Output)'" +#9 + i; atf_check -s exit:0 -o empty -e empty \ + ${TEST_SH} -c '(echo line 1; echo line 2 > Out2) > Out1' + test "$(cat Out1)" = "line 1" || atf_fail \ + "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'" + test "$(cat Out2)" = "line 2" || atf_fail \ + "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'" +#10 + i; atf_check -s exit:0 -o empty -e empty \ + ${TEST_SH} -c '{ echo line 1; echo line 2 > Out2;} > Out1' + test "$(cat Out1)" = "line 1" || atf_fail \ + "#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'" + test "$(cat Out2)" = "line 2" || atf_fail \ + "#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'" +#11 + i; rm -f Out1 Out2 2>/dev/null || : + cat <<- 'EOF' | + for arg in 'line 1' 'line 2' 'line 3' + do + echo "$arg" + echo "$arg" > Out1 + done > Out2 + EOF + atf_check -s exit:0 -o empty -e empty ${TEST_SH} + test "$(cat Out1)" = "line 3" || atf_fail \ + "#$T: Incorrect Out1: Should be 'line 3' is '$(cat Out1)'" + test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \ + "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'" +#12 + i; rm -f Out1 Out2 2>/dev/null || : + cat <<- 'EOF' | + for arg in 'line 1' 'line 2' 'line 3' + do + echo "$arg" + echo "$arg" >> Out1 + done > Out2 + EOF + atf_check -s exit:0 -o empty -e empty ${TEST_SH} + test "$(cat Out1)" = "line 1${nl}line 2${nl}line 3" || atf_fail \ + "#$T: Incorrect Out1: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out1)'" + test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \ + "#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'" +} + +atf_test_case fd_redirections +fd_redirections_head() +{ + atf_set "descr" "Tests redirections to/from specific descriptors" +} +fd_redirections_body() +{ + # Or it will one day... +} + +atf_test_case local_redirections +local_redirections_head() +{ + atf_set "descr" \ + "Tests that exec can reassign file descriptors in the shell itself" +} +local_redirections_body() +{ + # Or it will one day... +} + atf_test_case redir_in_case -redir_in_case_head() { - atf_set "descr" "Tests that sh(1) allows plain redirections " \ +redir_in_case_head() +{ + atf_set "descr" "Tests that sh(1) allows just redirections " \ "in case statements. (PR bin/48631)" } -redir_in_case_body() { +redir_in_case_body() +{ atf_check -s exit:0 -o empty -e empty \ ${TEST_SH} -c 'case x in (whatever) >foo;; esac' + + atf_check -s exit:0 -o empty -e empty \ + ${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac' + + atf_check -s exit:0 -o empty -e empty \ + ${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac' + + atf_check -s exit:0 -o empty -e empty \ + ${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac' } +atf_test_case incorrect_redirections +incorrect_redirections_head() +{ + atf_set "descr" "Tests that sh(1) correctly ignores non-redirections" +} +incorrect_redirections_body() { + + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo>' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'read foo<' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'echo x > '"$nl" + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'read x < '"$nl" + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'echo x <> '"$nl" + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'echo x >< anything' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'echo x >>< anything' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'echo x >|< anything' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'echo x > ; read x < /dev/null || echo bad' + atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \ + 'read x < & echo y > /dev/null; wait && echo bad' + + rm -f Output 2>/dev/null || : + atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \ + ${TEST_SH} -c 'echo A Line \> Output' + test -f Output && atf_file "File 'Output' appeared and should not have" + + rm -f Output 2>/dev/null || : + atf_check -s exit:0 -e empty -o empty \ + ${TEST_SH} -c 'echo A Line \>> Output' + test -f Output || atf_file "File 'Output' not created when it should" + test "$(cat Output)" = 'A Line >' || atf_fail \ + "Output file contains '$(cat Output)' instead of '"'A Line >'\' + + rm -f Output \> 2>/dev/null || : + atf_check -s exit:0 -e empty -o empty \ + ${TEST_SH} -c 'echo A Line >\> Output' + test -f Output && atf_file "File 'Output' appeared and should not have" + test -f '>' || atf_file "File '>' not created when it should" + test "$(cat '>')" = 'A Line Output' || atf_fail \ + "Output file ('>') contains '$(cat '>')' instead of 'A Line Output'" +} + +# Many more tests in t_here, so here we have just rudimentary checks atf_test_case redir_here_doc -redir_here_doc_head() { +redir_here_doc_head() +{ atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \ "input redirections" } -redir_here_doc_body() { - +redir_here_doc_body() +{ + # nb: the printf is not executed, it is data cat <<- 'DONE' | cat <<EOF printf '%s\n' 'hello\n' EOF DONE - atf_check -s exit:0 -o match:'hello\\n' -e empty ${TEST_SH} + atf_check -s exit:0 -o match:printf -o match:'hello\\n' \ + -e empty ${TEST_SH} +} + +atf_test_case subshell_redirections +subshell_redirections_head() +{ + atf_set "descr" "Tests redirection interactions between shell and " \ + "its sub-shell(s)" +} +subshell_redirections_body() +{ + # Or will, one day } atf_init_test_cases() { - atf_add_test_case redir_in_case + atf_add_test_case basic_test_method_test + atf_add_test_case do_input_redirections + atf_add_test_case do_output_redirections + atf_add_test_case fd_redirections + atf_add_test_case local_redirections + atf_add_test_case incorrect_redirections atf_add_test_case redir_here_doc + atf_add_test_case redir_in_case + atf_add_test_case subshell_redirections }