Home | History | Annotate | Line # | Download | only in sh
t_here.sh revision 1.5
      1 # $NetBSD: t_here.sh,v 1.5 2016/03/27 14:52:40 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 reset()
     34 {
     35 	TEST_NUM=0
     36 	TEST_FAILURES=''
     37 	TEST_FAIL_COUNT=0
     38 	TEST_ID="$1"
     39 }
     40 
     41 check()
     42 {
     43 	fail=false
     44 	TEMP_FILE=$( mktemp OUT.XXXXXX )
     45 	TEST_NUM=$(( $TEST_NUM + 1 ))
     46 
     47 	# our local shell (ATF_SHELL) better do quoting correctly...
     48 	# some of the tests expect us to expand $nl internally...
     49 	CMD="nl='${nl}'; $1"
     50 
     51 	result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
     52 	STATUS=$?
     53 
     54 	if [ "${STATUS}" -ne "$3" ]; then
     55 		echo >&2 "[$TEST_NUM] expected exit code $3, got ${STATUS}"
     56 
     57 		# don't actually fail just because of wrong exit code
     58 		# unless we either expected, or received "good"
     59 		case "$3/${STATUS}" in
     60 		(*/0|0/*) fail=true;;
     61 		esac
     62 	fi
     63 
     64 	if [ "$3" -eq 0 ]; then
     65 		if [ -s "${TEMP_FILE}" ]; then
     66 			echo >&2 \
     67 			 "[$TEST_NUM] Messages produced on stderr unexpected..."
     68 			cat "${TEMP_FILE}" >&2
     69 			fail=true
     70 		fi
     71 	else
     72 		if ! [ -s "${TEMP_FILE}" ]; then
     73 			echo >&2 \
     74 		    "[$TEST_NUM] Expected messages on stderr, nothing produced"
     75 			fail=true
     76 		fi
     77 	fi
     78 	rm -f "${TEMP_FILE}"
     79 
     80 	# Remove newlines (use local shell for this)
     81 	oifs="$IFS"
     82 	IFS="$nl"
     83 	result="$(echo $result)"
     84 	IFS="$oifs"
     85 	if [ "$2" != "$result" ]
     86 	then
     87 		echo >&2 "[$TEST_NUM] Expected output '$2', received '$result'"
     88 		fail=true
     89 	fi
     90 
     91 	$fail && test -n "$TEST_ID" && {
     92 		TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+
     93 }${TEST_ID}[$TEST_NUM]: test of '$1' failed";
     94 		TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
     95 		return 0
     96 	}
     97 	$fail && atf_fail "Test[$TEST_NUM] of '$1' failed"
     98 	return 0
     99 }
    100 
    101 results()
    102 {
    103 	test -z "${TEST_ID}" && return 0
    104 	test -z "${TEST_FAILURES}" && return 0
    105 
    106 	echo >&2 "=========================================="
    107 	echo >&2 "While testing '${TEST_ID}'"
    108 	echo >&2 " - - - - - - - - - - - - - - - - -"
    109 	echo >&2 "${TEST_FAILURES}"
    110 	atf_fail \
    111  "Test ${TEST_ID}: $TEST_FAIL_COUNT subtests (of $TEST_NUM) failed - see stderr"
    112 }
    113 
    114 atf_test_case do_simple
    115 do_simple_head() {
    116 	atf_set "descr" "Basic tests for here documents"
    117 }
    118 do_simple_body() {
    119 	y=x
    120 
    121 	reset 'simple'
    122 	IFS=' 	'
    123 	check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
    124 	check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
    125 
    126 	check "y=${y};"'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
    127 			'text' 0
    128 	check "y=${y};"'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
    129 			'te${y}t' 0
    130 	check "y=${y};"'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
    131 			'te${y}t' 0
    132 	check "y=${y};"'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
    133 			'te${y}t' 0
    134 
    135 	# check that quotes in the here doc survive and cause no problems
    136 	check "cat <<EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
    137 	check "cat <<\EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
    138 	check "cat <<'EOF'${nl}te'xt${nl}EOF$nl" "te'xt" 0
    139 	check "cat <<EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    140 	check "cat <<\EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    141 	check "cat <<'EOF'${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    142 	check "cat <<'EO'F${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
    143 
    144 	check "y=${y};"'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' \
    145 			'te'"'"'xt' 0
    146 	check "y=${y};"'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' \
    147 			'te'"''"'xt' 0
    148 
    149 	# note that the blocks of empty space in the following must
    150 	# be entirely tab characters, no spaces.
    151 
    152 	check 'x=`cat <<EOF'"$nl	text${nl}EOF$nl"'`; echo "$x"' \
    153 			'	text' 0
    154 	check 'x=`cat <<-EOF'"$nl	text${nl}EOF$nl"'`; echo $x' \
    155 			'text' 0
    156 	check 'x=`cat <<-EOF'"${nl}text${nl}	EOF$nl"'`; echo $x' \
    157 			'text' 0
    158 	check 'x=`cat <<-\EOF'"$nl	text${nl}	EOF$nl"'`; echo $x' \
    159 			'text' 0
    160 	check 'x=`cat <<- "EOF"'"$nl	text${nl}EOF$nl"'`; echo $x' \
    161 			'text' 0
    162 	check 'x=`cat <<- '"'EOF'${nl}text${nl}	EOF$nl"'`; echo $x' \
    163 			'text' 0
    164 	results
    165 }
    166 
    167 atf_test_case end_markers
    168 end_markers_head() {
    169 	atf_set "descr" "Tests for various end markers of here documents"
    170 }
    171 end_markers_body() {
    172 
    173 	reset 'end_markers'
    174 	for end in EOF 1 \! '$$$' "string " a\\\  '&' '' ' ' '  ' --STRING-- . '~~~' \
    175 VERYVERYVERYVERYLONGLONGLONGin_fact_absurdly_LONG_LONG_HERE_DOCUMENT_TERMINATING_MARKER_THAT_goes_On_forever_and_ever_and_ever...
    176 	do
    177 		# check unquoted end markers
    178 		case "${end}" in
    179 		('' | *[' $&#*~']* ) ;;	# skip unquoted endmark test for these
    180 		(*)	check \
    181 	'x=$(cat << '"${end}${nl}text${nl}${end}${nl}"'); echo "$x"' 'text' 0
    182 			;;
    183 		esac
    184 
    185 		# and quoted end markers
    186 		check \
    187 	'x=$(cat <<'"'${end}'${nl}text${nl}${end}${nl}"'); echo "$x"' 'text' 0
    188 
    189 		# and see what happens if we encounter "almost" an end marker
    190 		case "${#end}" in
    191 		(0|1)	;;		# too short to try truncation tests
    192 		(*)	check \
    193    'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}${nl}${end}${nl}"'); echo "$x"' \
    194 				"text ${end%?}" 0
    195 			check \
    196    'x=$(cat <<'"'${end}'${nl}text${nl}${end#?}${nl}${end}${nl}"'); echo "$x"' \
    197 				"text ${end#?}" 0
    198 			check \
    199    'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}+${nl}${end}${nl}"');echo "$x"' \
    200 				"text ${end%?}+" 0
    201 			;;
    202 		esac
    203 
    204 		# or something that is a little longer
    205 		check \
    206    'x=$(cat <<'"'${end}'${nl}text${nl}${end}x${nl}${end}${nl}"'); echo "$x"' \
    207 				"text ${end}x" 0
    208 		check \
    209     'x=$(cat <<'"'${end}'${nl}text${nl}!${end}${nl}${end}${nl}"'); echo "$x"' \
    210 				"text !${end}" 0
    211 
    212 		# or which does not begin at start of line
    213 		check \
    214     'x=$(cat <<'"'${end}'${nl}text${nl} ${end}${nl}${end}${nl}"'); echo "$x"' \
    215 				"text  ${end}" 0
    216 		check \
    217     'x=$(cat <<'"'${end}'${nl}text${nl}	${end}${nl}${end}${nl}"'); echo "$x"' \
    218 				"text 	${end}" 0
    219 
    220 		# or end at end of line
    221 		check \
    222     'x=$(cat <<'"'${end}'${nl}text${nl}${end} ${nl}${end}${nl}"'); echo "$x"' \
    223 				"text ${end} " 0
    224 
    225 		# or something that is correct much of the way, but then...
    226 
    227 		case "${#end}" in
    228 		(0)	;;		# cannot test this one
    229 		(1)	check \
    230     'x=$(cat <<'"'${end}'${nl}text${nl}${end}${end}${nl}${end}${nl}"'); echo "$x"' \
    231 				"text ${end}${end}" 0
    232 			;;
    233 		(2-7)	pfx="${end%?}"
    234 			check \
    235     'x=$(cat <<'"'${end}'${nl}text${nl}${end}${pfx}${nl}${end}${nl}"'); echo "$x"' \
    236 				"text ${end}${pfx}" 0
    237 			check \
    238     'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); echo "$x"' \
    239 				"text ${pfx}${end}" 0
    240 			;;
    241 		(*)	pfx=${end%??????}; sfx=${end#??????}
    242 			check \
    243     'x=$(cat <<'"'${end}'${nl}text${nl}${end}${sfx}${nl}${end}${nl}"'); echo "$x"' \
    244 				"text ${end}${sfx}" 0
    245 			check \
    246     'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); echo "$x"' \
    247 				"text ${pfx}${end}" 0
    248 			check \
    249     'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${sfx}${nl}${end}${nl}"'); echo "$x"' \
    250 				"text ${pfx}${sfx}" 0
    251 			;;
    252 		esac
    253 	done
    254 
    255 	# Add striptabs tests (in similar way) here one day...
    256 
    257 	results
    258 }
    259 
    260 atf_test_case incomplete
    261 incomplete_head() {
    262 	atf_set "descr" "Basic tests for incomplete here documents"
    263 }
    264 incomplete_body() {
    265 	reset incomplete
    266 
    267 	check 'cat <<EOF' '' 2
    268 	check 'cat <<- EOF' '' 2
    269 	check 'cat <<\EOF' '' 2
    270 	check 'cat <<- \EOF' '' 2
    271 
    272 	check 'cat <<EOF'"${nl}" '' 2
    273 	check 'cat <<- EOF'"${nl}" '' 2
    274 	check 'cat <<'"'EOF'${nl}" '' 2
    275 	check 'cat <<- "EOF"'"${nl}" '' 2
    276 
    277 	check 'cat << EOF'"${nl}${nl}" '' 2
    278 	check 'cat <<-EOF'"${nl}${nl}" '' 2
    279 	check 'cat << '"'EOF'${nl}${nl}" '' 2
    280 	check 'cat <<-"EOF"'"${nl}${nl}" '' 2
    281 
    282 	check 'cat << EOF'"${nl}"'line 1'"${nl}" '' 2
    283 	check 'cat <<-EOF'"${nl}"'	line 1'"${nl}" '' 2
    284 	check 'cat << EOF'"${nl}"'line 1'"${nl}"'	line 2'"${nl}" '' 2
    285 	check 'cat <<-EOF'"${nl}"'	line 1'"${nl}"'line 2'"${nl}" '' 2
    286 
    287 	check 'cat << EOF'"${nl}line 1${nl}${nl}line3${nl}${nl}5!${nl}" '' 2
    288 
    289 	results
    290 }
    291 
    292 atf_test_case lineends
    293 lineends_head() {
    294 	atf_set "descr" "Tests for line endings in here documents"
    295 }
    296 lineends_body() {
    297 	reset lineends
    298 
    299 	# note that "check" removes newlines from stdout before comparing.
    300 	# (they become blanks, provided there is something before & after)
    301 
    302 	check 'cat << \echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" '\' 0
    303 	check 'cat <<  echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" 'echo' 0
    304 	check 'cat << echo'"${nl}"'\\'"${nl}echo${nl}echo${nl}" '\' 0
    305 
    306 	check 'X=3; cat << ec\ho'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
    307 		'$X\'  0
    308 	check 'X=3; cat <<  echo'"${nl}"'$X'"${nl}echo${nl}echo${nl}" \
    309 		'3'  0
    310 	check 'X=3; cat <<  echo'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
    311 		''  0
    312 	check 'X=3; cat <<  echo'"${nl}"'${X}\'"${nl}echo${nl}echo${nl}" \
    313 		'3echo'  0
    314 	check 'X=3; cat <<  echo'"${nl}"'\$X\'"${nl}echo${nl}echo${nl}" \
    315 		'$Xecho'  0
    316 	check 'X=3; cat <<  echo'"${nl}"'\\$X \'"${nl}echo${nl}echo${nl}" \
    317 		'\3 echo'  0
    318 
    319 	check \
    320   'cat << "echo"'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
    321 		 'line1\ line2\'  0
    322 	check \
    323 	  'cat << echo'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
    324 	  'line1line2echo'  0
    325 
    326 	results
    327 }
    328 
    329 atf_test_case multiple
    330 multiple_head() {
    331 	atf_set "descr" "Tests for multiple here documents on one cmd line"
    332 }
    333 multiple_body() {
    334 	reset multiple
    335 
    336 	check \
    337     "(cat ; cat <&3) <<EOF0 3<<EOF3${nl}STDIN${nl}EOF0${nl}-3-${nl}EOF3${nl}" \
    338 		'STDIN -3-' 0
    339 
    340 	check "(read line; echo \"\$line\"; cat <<EOF1; echo \"\$line\") <<EOF2
    341 The File
    342 EOF1
    343 The Line
    344 EOF2
    345 "			'The Line The File The Line' 0
    346 
    347 	check "(read line; echo \"\$line\"; cat <<EOF; echo \"\$line\") <<EOF
    348 The File
    349 EOF
    350 The Line
    351 EOF
    352 "			'The Line The File The Line' 0
    353 
    354 	check "V=1; W=2; cat <<-1; cat <<2; cat <<- 3; cat <<'4';"' cat <<\5
    355 		$V
    356 		$W
    357 		3
    358 	4
    359 	5
    360 			1
    361 2
    362 	5
    363 					4*$W+\$V
    364 	3
    365 $W
    366 1
    367 2
    368 3
    369 4
    370 7+$V
    371 $W+6
    372 5
    373 '			'1 2 3 4 5 5 4*2+$V $W 1 2 3 7+$V $W+6'	0
    374 
    375 	results
    376 }
    377 
    378 atf_test_case nested
    379 nested_head() {
    380 	atf_set "descr" "Tests for nested here documents for one cmd"
    381 }
    382 nested_body() {
    383 	reset nested
    384 
    385 	check \
    386 'cat << EOF1'"${nl}"'$(cat << EOF2'"${nl}LINE${nl}EOF2${nl}"')'"${nl}EOF1${nl}"\
    387 	'LINE' 0
    388 
    389 # This next one fails ... and correctly, so we will omit it (bad test)
    390 # Reasoning is that the correct data "$(cat << EOF2)\nLINE\nEOF2\n" is
    391 # collected for the outer (EOF1) heredoc, when that is parsed, it looks
    392 # like
    393 #	$(cat <<EOF2)
    394 #	LINE
    395 #	EOF2
    396 # which looks like a good command - except it is being parsed in "heredoc"
    397 # syntax, which means it is enclosed in double quotes, which means that
    398 # the newline after the ')' in the first line is not a newline token, but
    399 # just a character.  The EOF2 heredoc cannot start until after the next
    400 # newline token, of which there are none here...  LINE and EOF2 are just
    401 # more data in the outer EOF1 heredoc for its "cat" command to read & write.
    402 #
    403 # The previous sub-test works because there the \n comes inside the
    404 # $( ), and in there, the outside quoting rules are suspended, and it
    405 # all starts again - so that \n is a newline token, and the EOF2 heredoc
    406 # is processed.
    407 #
    408 #	check \
    409 #   'cat << EOF1'"${nl}"'$(cat << EOF2 )'"${nl}LINE${nl}EOF2${nl}EOF1${nl}" \
    410 #	'LINE' 0
    411 
    412 	L='cat << EOF1'"${nl}"'LINE1$(cat << EOF2'"${nl}"
    413 	L="${L}"'LINE2$(cat << EOF3'"${nl}"
    414 	L="${L}"'LINE3$(cat << EOF4'"${nl}"
    415 	L="${L}"'LINE4$(cat << EOF5'"${nl}"
    416 	L="${L}LINE5${nl}EOF5${nl})4${nl}EOF4${nl})3${nl}"
    417 	L="${L}EOF3${nl})2${nl}EOF2${nl})1${nl}EOF1${nl}"
    418 
    419 	# That mess is ...
    420 	#
    421 	#	cat <<EOF1
    422 	#	LINE1$(cat << EOF2
    423 	#	LINE2$(cat << EOF3
    424 	#	LINE3$(cat << EOF4
    425 	#	LINE4$(cat << EOF5
    426 	#	LINE5
    427 	#	EOF5
    428 	#	)4
    429 	#	EOF4
    430 	#	)3
    431 	#	EOF3
    432 	#	)2
    433 	#	EOF2
    434 	#	)1
    435 	#	EOF1
    436 
    437 	check "${L}" 'LINE1LINE2LINE3LINE4LINE54321' 0
    438 
    439 	results
    440 }
    441 
    442 atf_test_case quoting
    443 quoting_head() {
    444 	atf_set "descr" "Tests for use of quotes inside here documents"
    445 }
    446 quoting_body() {
    447 	reset quoting
    448 
    449 	check 'X=!; cat <<- E\0F
    450 		<'\''"'\'' \\$X\$X  "'\''" \\>
    451 	E0F
    452 	'	'<'\''"'\'' \\$X\$X  "'\''" \\>'	0
    453 
    454 	check 'X=!; cat <<- E0F
    455 		<'\''"'\'' \\$X\$X  "'\''" \\>
    456 	E0F
    457 	'	'<'\''"'\'' \!$X  "'\''" \>'	0
    458 
    459 	check 'cat <<- END
    460 		$( echo "'\''" ) $( echo '\''"'\'' ) $( echo \\ )
    461 	END
    462 	'	"' \" \\"		0
    463 
    464 	check 'X=12345; Y="string1 line1?-line2"; Z=; unset W; cat <<-EOF
    465 		${#X}${Z:-${Y}}${W+junk}${Y%%l*}${Y#*\?}
    466 		"$Z"'\''$W'\'' ${Y%" "*} $(( X + 54321 ))
    467 	EOF
    468 	'	'5string1 line1?-line2string1 -line2 ""'\'\'' string1 66666' 0
    469 
    470 	results
    471 }
    472 
    473 atf_test_case side_effects
    474 side_effects_head() {
    475 	atf_set "descr" "Tests how side effects in here documents are handled"
    476 }
    477 side_effects_body() {
    478 
    479 	atf_check -s exit:0 -o inline:'2\n1\n' -e empty ${TEST_SH} -c '
    480 		unset X
    481 		cat <<-EOF
    482 		${X=2}
    483 		EOF
    484 		echo "${X-1}"
    485 		'
    486 }
    487 
    488 atf_test_case vicious
    489 vicious_head() {
    490 	atf_set "descr" "Tests for obscure and obnoxious uses of here docs"
    491 }
    492 vicious_body() {
    493 	reset
    494 
    495 	cat <<- \END_SCRIPT > script
    496 		cat <<ONE && cat \
    497 		<<TWO
    498 		a
    499 		ONE
    500 		b
    501 		TWO
    502 	END_SCRIPT
    503 
    504 	atf_check -s exit:0 -o inline:'a\nb\n' -e empty ${TEST_SH} script
    505 
    506 	# This next one is causing discussion currently (late Feb 2016)
    507 	# amongst stds writers & implementors.   Consequently we
    508 	# will not check what it produces.   The eventual result
    509 	# seems unlikely to be what we currently output, which
    510 	# is:
    511 	#	A:echo line 1
    512 	#	B:echo line 2)" && prefix DASH_CODE <<DASH_CODE
    513 	#	B:echo line 3
    514 	#	line 4
    515 	#	line 5
    516 	#
    517 	# The likely intended output is ...
    518 	#
    519 	#	A:echo line 3
    520 	#	B:echo line 1
    521 	#	line 2
    522 	#	DASH_CODE:echo line 4)"
    523 	#	DASH_CODE:echo line 5
    524 	#
    525 	# The difference is explained by differing opinions on just
    526 	# when processing of a here doc should start
    527 
    528 	cat <<- \END_SCRIPT > script
    529 		prefix() { sed -e "s/^/$1:/"; }
    530 		DASH_CODE() { :; }
    531 
    532 		prefix A <<XXX && echo "$(prefix B <<XXX
    533 		echo line 1
    534 		XXX
    535 		echo line 2)" && prefix DASH_CODE <<DASH_CODE
    536 		echo line 3
    537 		XXX
    538 		echo line 4)"
    539 		echo line 5
    540 		DASH_CODE
    541 	END_SCRIPT
    542 
    543 	# we will just verify that the shell can parse the
    544 	# script somehow, and doesn't fall over completely...
    545 
    546 	atf_check -s exit:0 -o ignore -e empty ${TEST_SH} script
    547 }
    548 
    549 atf_init_test_cases() {
    550 	atf_add_test_case do_simple	# not worthy of a comment
    551 	atf_add_test_case end_markers	# the mundane, the weird, the bizarre
    552 	atf_add_test_case incomplete	# where the end marker isn't...
    553 	atf_add_test_case lineends	# test weird line endings in heredocs
    554 	atf_add_test_case multiple	# multiple << operators on one cmd
    555 	atf_add_test_case nested	# here docs inside here docs
    556 	atf_add_test_case quoting	# stuff quoted inside
    557 	atf_add_test_case side_effects	# here docs that modify environment
    558 	atf_add_test_case vicious	# evil test from the austin-l list...
    559 }
    560