Home | History | Annotate | Line # | Download | only in sh
t_here.sh revision 1.2
      1 # $NetBSD: t_here.sh,v 1.2 2016/02/29 23:52:53 christos Exp $
      2 #
      3 # Copyright (c) 2007 The NetBSD Foundation, Inc.
      4 # All rights reserved.
      5 #
      6 # Redistribution and use in source and binary forms, with or without
      7 # modification, are permitted provided that the following conditions
      8 # are met:
      9 # 1. Redistributions of source code must retain the above copyright
     10 #    notice, this list of conditions and the following disclaimer.
     11 # 2. Redistributions in binary form must reproduce the above copyright
     12 #    notice, this list of conditions and the following disclaimer in the
     13 #    documentation and/or other materials provided with the distribution.
     14 #
     15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25 # POSSIBILITY OF SUCH DAMAGE.
     26 #
     27 # the implementation of "sh" to test
     28 : ${TEST_SH:="/bin/sh"}
     29 
     30 nl='
     31 '
     32 
     33 check()
     34 {
     35 	fail=false
     36 	TEMP_FILE=$( mktemp OUT.XXXXXX )
     37 
     38 	# our local shell (ATF_SHELL) better do quoting correctly...
     39 	# some of the tests expect us to expand $nl internally...
     40 	CMD="nl='${nl}'; $1"
     41 
     42 echo "${CMD}" >/tmp/CMD
     43 	rm -f trace.*
     44 	result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
     45 	STATUS=$?
     46 
     47 	if [ -s "${O_FILE}" ]; then
     48 		echo >&2 "unexpected shell output noise on stdout"
     49 		cat "${O_FILE}" >&2
     50 		fail=true
     51 	fi
     52 
     53 	if [ "${STATUS}" -ne "$3" ]; then
     54 		echo >&2 "expected exit code $3, got ${STATUS}"
     55 
     56 		# don't actually fail just because of wrong exit code
     57 		# unless we either expected, or received "good"
     58 		case "$3/${STATUS}" in
     59 		(*/0|0/*) fail=true;;
     60 		esac
     61 	fi
     62 
     63 	if [ "$3" -eq 0 ]; then
     64 		if [ -s "${TEMP_FILE}" ]; then
     65 			echo >&2 "Messages produced on stderr unexpected..."
     66 			cat "${TEMP_FILE}" >&2
     67 			fail=true
     68 		fi
     69 	else
     70 		if ! [ -s "${TEMP_FILE}" ]; then
     71 			echo >&2 "Expected messages on stderr, nothing produced"
     72 			fail=true
     73 		fi
     74 	fi
     75 	rm -f "${TEMP_FILE}"
     76 
     77 	# Remove newlines (use local shell for this)
     78 	oifs="$IFS"
     79 	IFS="$nl"
     80 	result="$(echo $result)"
     81 	IFS="$oifs"
     82 	if [ "$2" != "$result" ]
     83 	then
     84 		echo >&2 "Expected output '$2', received '$result'"
     85 		fail=true
     86 	fi
     87 
     88 	$fail && atf_fail "test of '$1' failed"
     89 	return 0
     90 }
     91 
     92 atf_test_case do_simple
     93 do_simple_head() {
     94 	atf_set "descr" "Basic tests for here documents"
     95 }
     96 do_simple_body() {
     97 	y=x
     98 
     99 	IFS=
    100 	check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
    101 	check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
    102 
    103 	check "y=${y};"'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
    104 			'text' 0
    105 	check "y=${y};"'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
    106 			'te${y}t' 0
    107 	check "y=${y};"'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
    108 			'te${y}t' 0
    109 	check "y=${y};"'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
    110 			'te${y}t' 0
    111 
    112 	# check that quotes in the here doc survive and cause no problems
    113 	check "cat <<EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
    114 	check "cat <<\EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
    115 	check "cat <<'EOF'${nl}te'xt${nl}EOF$nl" "te'xt" 0
    116 	check "cat <<EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    117 	check "cat <<\EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    118 	check "cat <<'EOF'${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    119 	check "cat <<'EO'F${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    120 
    121 	check "y=${y};"'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' \
    122 			'te'"'"'xt' 0
    123 	check "y=${y};"'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' \
    124 			'te'"''"'xt' 0
    125 
    126 	# note that the blocks of empty space in the following must
    127 	# be entirely tab characters, no spaces.
    128 
    129 	check 'x=`cat <<EOF'"$nl	text${nl}EOF$nl"'`; echo "$x"' \
    130 			'	text' 0
    131 	check 'x=`cat <<-EOF'"$nl	text${nl}EOF$nl"'`; echo $x' \
    132 			'text' 0
    133 	check 'x=`cat <<-EOF'"${nl}text${nl}	EOF$nl"'`; echo $x' \
    134 			'text' 0
    135 	check 'x=`cat <<-\EOF'"$nl	text${nl}	EOF$nl"'`; echo $x' \
    136 			'text' 0
    137 	check 'x=`cat <<- "EOF"'"$nl	text${nl}EOF$nl"'`; echo $x' \
    138 			'text' 0
    139 	check 'x=`cat <<- '"'EOF'${nl}text${nl}	EOF$nl"'`; echo $x' \
    140 			'text' 0
    141 }
    142 
    143 atf_test_case incomplete
    144 incomplete_head() {
    145 	atf_set "descr" "Basic tests for incomplete here documents"
    146 }
    147 incomplete_body() {
    148 	check 'cat <<EOF' '' 2
    149 	check 'cat <<- EOF' '' 2
    150 	check 'cat <<\EOF' '' 2
    151 	check 'cat <<- \EOF' '' 2
    152 
    153 	check 'cat <<EOF'"${nl}" '' 2
    154 	check 'cat <<- EOF'"${nl}" '' 2
    155 	check 'cat <<'"'EOF'${nl}" '' 2
    156 	check 'cat <<- "EOF"'"${nl}" '' 2
    157 
    158 	check 'cat << EOF'"${nl}${nl}" '' 2
    159 	check 'cat <<-EOF'"${nl}${nl}" '' 2
    160 	check 'cat << '"'EOF'${nl}${nl}" '' 2
    161 	check 'cat <<-"EOF"'"${nl}${nl}" '' 2
    162 
    163 	check 'cat << EOF'"${nl}"'line 1'"${nl}" '' 2
    164 	check 'cat <<-EOF'"${nl}"'	line 1'"${nl}" '' 2
    165 	check 'cat << EOF'"${nl}"'line 1'"${nl}"'	line 2'"${nl}" '' 2
    166 	check 'cat <<-EOF'"${nl}"'	line 1'"${nl}"'line 2'"${nl}" '' 2
    167 
    168 	check 'cat << EOF'"${nl}line 1${nl}${nl}line3${nl}${nl}5!${nl}" '' 2
    169 }
    170 
    171 atf_test_case multiple
    172 multiple_head() {
    173 	atf_set "descr" "Tests for multiple here documents for one cmd"
    174 }
    175 multiple_body() {
    176 	check \
    177     "(cat ; cat <&3) <<EOF0 3<<EOF3${nl}STDIN${nl}EOF0${nl}-3-${nl}EOF3${nl}" \
    178 		'STDIN -3-' 0
    179 
    180 	check "(read line; echo \"\$line\"; cat <<EOF1; echo \"\$line\") <<EOF2
    181 The File
    182 EOF1
    183 The Line
    184 EOF2
    185 "			'The Line The File The Line' 0
    186 
    187 	check "(read line; echo \"\$line\"; cat <<EOF; echo \"\$line\") <<EOF
    188 The File
    189 EOF
    190 The Line
    191 EOF
    192 "			'The Line The File The Line' 0
    193 
    194 }
    195 
    196 atf_test_case viscious
    197 viscious_head() {
    198 	atf_set "descr" "Tests for obscure and obnoxious uses of here docs"
    199 }
    200 viscious_body() {
    201 
    202 	cat <<- \END_SCRIPT > script
    203 		cat <<ONE && cat \
    204 		<<TWO
    205 		a
    206 		ONE
    207 		b
    208 		TWO
    209 	END_SCRIPT
    210 
    211 	atf_check -s exit:0 -o inline:'a\nb\n' -e empty ${TEST_SH} script
    212 
    213 	# This next one is causing discussion currently (late Feb 2016)
    214 	# amongst stds writers & implementors.   Consequently we
    215 	# will not check what it produces.   The eventual result
    216 	# seems unlikely to be what we currently output, which
    217 	# is:
    218 	#	:echo line 1
    219 	#	B:echo line 2)" && prefix DASH_CODE <<DASH_CODE
    220 	#	B:echo line 3
    221 	#	line 4
    222 	#	line 5
    223 	#
    224 	# The likely intended output is ...
    225 	#
    226 	#	A:echo line 3
    227 	#	B:echo line 1
    228 	#	line 2
    229 	#	DASH_CODE:echo line 4)"
    230 	#	DASH_CODE:echo line 5
    231 	#
    232 	# The difference is explained by differeng opinions on just
    233 	# when processing of a here doc should start
    234 
    235 	cat <<- \END_SCRIPT > script
    236 		prefix() { sed -e "s/^/$1:/"; }
    237 		DASH_CODE() { :; }
    238 
    239 		prefix A <<XXX && echo "$(prefix B <<XXX
    240 		echo line 1
    241 		XXX
    242 		echo line 2)" && prefix DASH_CODE <<DASH_CODE
    243 		echo line 3
    244 		XXX
    245 		echo line 4)"
    246 		echo line 5
    247 		DASH_CODE
    248 	END_SCRIPT
    249 
    250 	# we will just verify that the shell can parse the
    251 	# script somehow, and doesn't fall over completely...
    252 
    253 	atf_check -s exit:0 -o ignore -e empty ${TEST+SH} script
    254 }
    255 
    256 atf_init_test_cases() {
    257 	atf_add_test_case do_simple
    258 	atf_add_test_case incomplete
    259 	atf_add_test_case multiple	# multiple << operators on one cmd
    260 	atf_add_test_case viscious	# evil test from the austin-l list...
    261 }
    262