xref: /freebsd/contrib/netbsd-tests/bin/sh/t_here.sh (revision 640235e2)
1*640235e2SEnji Cooper# $NetBSD: t_here.sh,v 1.6 2016/03/31 16:21:52 christos Exp $
257718be8SEnji Cooper#
357718be8SEnji Cooper# Copyright (c) 2007 The NetBSD Foundation, Inc.
457718be8SEnji Cooper# All rights reserved.
557718be8SEnji Cooper#
657718be8SEnji Cooper# Redistribution and use in source and binary forms, with or without
757718be8SEnji Cooper# modification, are permitted provided that the following conditions
857718be8SEnji Cooper# are met:
957718be8SEnji Cooper# 1. Redistributions of source code must retain the above copyright
1057718be8SEnji Cooper#    notice, this list of conditions and the following disclaimer.
1157718be8SEnji Cooper# 2. Redistributions in binary form must reproduce the above copyright
1257718be8SEnji Cooper#    notice, this list of conditions and the following disclaimer in the
1357718be8SEnji Cooper#    documentation and/or other materials provided with the distribution.
1457718be8SEnji Cooper#
1557718be8SEnji Cooper# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1657718be8SEnji Cooper# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1757718be8SEnji Cooper# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1857718be8SEnji Cooper# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
1957718be8SEnji Cooper# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2057718be8SEnji Cooper# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2157718be8SEnji Cooper# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2257718be8SEnji Cooper# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2357718be8SEnji Cooper# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2457718be8SEnji Cooper# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2557718be8SEnji Cooper# POSSIBILITY OF SUCH DAMAGE.
2657718be8SEnji Cooper#
27*640235e2SEnji Cooper# the implementation of "sh" to test
28*640235e2SEnji Cooper: ${TEST_SH:="/bin/sh"}
2957718be8SEnji Cooper
3057718be8SEnji Coopernl='
3157718be8SEnji Cooper'
3257718be8SEnji Cooper
33*640235e2SEnji Cooperreset()
34*640235e2SEnji Cooper{
35*640235e2SEnji Cooper	TEST_NUM=0
36*640235e2SEnji Cooper	TEST_FAILURES=''
37*640235e2SEnji Cooper	TEST_FAIL_COUNT=0
38*640235e2SEnji Cooper	TEST_ID="$1"
39*640235e2SEnji Cooper}
40*640235e2SEnji Cooper
4157718be8SEnji Coopercheck()
4257718be8SEnji Cooper{
43*640235e2SEnji Cooper	fail=false
44*640235e2SEnji Cooper	TEMP_FILE=$( mktemp OUT.XXXXXX )
45*640235e2SEnji Cooper	TEST_NUM=$(( $TEST_NUM + 1 ))
46*640235e2SEnji Cooper
47*640235e2SEnji Cooper	# our local shell (ATF_SHELL) better do quoting correctly...
48*640235e2SEnji Cooper	# some of the tests expect us to expand $nl internally...
49*640235e2SEnji Cooper	CMD="nl='${nl}'; $1"
50*640235e2SEnji Cooper
51*640235e2SEnji Cooper	result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
52*640235e2SEnji Cooper	STATUS=$?
53*640235e2SEnji Cooper
54*640235e2SEnji Cooper	if [ "${STATUS}" -ne "$3" ]; then
55*640235e2SEnji Cooper		echo >&2 "[$TEST_NUM] expected exit code $3, got ${STATUS}"
56*640235e2SEnji Cooper
57*640235e2SEnji Cooper		# don't actually fail just because of wrong exit code
58*640235e2SEnji Cooper		# unless we either expected, or received "good"
59*640235e2SEnji Cooper		case "$3/${STATUS}" in
60*640235e2SEnji Cooper		(*/0|0/*) fail=true;;
61*640235e2SEnji Cooper		esac
62*640235e2SEnji Cooper	fi
63*640235e2SEnji Cooper
64*640235e2SEnji Cooper	if [ "$3" -eq 0 ]; then
65*640235e2SEnji Cooper		if [ -s "${TEMP_FILE}" ]; then
66*640235e2SEnji Cooper			echo >&2 \
67*640235e2SEnji Cooper			 "[$TEST_NUM] Messages produced on stderr unexpected..."
68*640235e2SEnji Cooper			cat "${TEMP_FILE}" >&2
69*640235e2SEnji Cooper			fail=true
70*640235e2SEnji Cooper		fi
71*640235e2SEnji Cooper	else
72*640235e2SEnji Cooper		if ! [ -s "${TEMP_FILE}" ]; then
73*640235e2SEnji Cooper			echo >&2 \
74*640235e2SEnji Cooper		    "[$TEST_NUM] Expected messages on stderr, nothing produced"
75*640235e2SEnji Cooper			fail=true
76*640235e2SEnji Cooper		fi
77*640235e2SEnji Cooper	fi
78*640235e2SEnji Cooper	rm -f "${TEMP_FILE}"
79*640235e2SEnji Cooper
80*640235e2SEnji Cooper	# Remove newlines (use local shell for this)
8157718be8SEnji Cooper	oifs="$IFS"
8257718be8SEnji Cooper	IFS="$nl"
8357718be8SEnji Cooper	result="$(echo $result)"
8457718be8SEnji Cooper	IFS="$oifs"
8557718be8SEnji Cooper	if [ "$2" != "$result" ]
8657718be8SEnji Cooper	then
87*640235e2SEnji Cooper		echo >&2 "[$TEST_NUM] Expected output '$2', received '$result'"
88*640235e2SEnji Cooper		fail=true
8957718be8SEnji Cooper	fi
90*640235e2SEnji Cooper
91*640235e2SEnji Cooper	if $fail
92*640235e2SEnji Cooper	then
93*640235e2SEnji Cooper		echo >&2 "[$TEST_NUM] Full command: <<${CMD}>>"
94*640235e2SEnji Cooper	fi
95*640235e2SEnji Cooper
96*640235e2SEnji Cooper	$fail && test -n "$TEST_ID" && {
97*640235e2SEnji Cooper		TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+
98*640235e2SEnji Cooper}${TEST_ID}[$TEST_NUM]: test of '$1' failed";
99*640235e2SEnji Cooper		TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
100*640235e2SEnji Cooper		return 0
101*640235e2SEnji Cooper	}
102*640235e2SEnji Cooper	$fail && atf_fail "Test[$TEST_NUM] of '$1' failed"
103*640235e2SEnji Cooper	return 0
10457718be8SEnji Cooper}
10557718be8SEnji Cooper
106*640235e2SEnji Cooperresults()
107*640235e2SEnji Cooper{
108*640235e2SEnji Cooper	test -z "${TEST_ID}" && return 0
109*640235e2SEnji Cooper	test -z "${TEST_FAILURES}" && return 0
110*640235e2SEnji Cooper
111*640235e2SEnji Cooper	echo >&2 "=========================================="
112*640235e2SEnji Cooper	echo >&2 "While testing '${TEST_ID}'"
113*640235e2SEnji Cooper	echo >&2 " - - - - - - - - - - - - - - - - -"
114*640235e2SEnji Cooper	echo >&2 "${TEST_FAILURES}"
115*640235e2SEnji Cooper	atf_fail \
116*640235e2SEnji Cooper "Test ${TEST_ID}: $TEST_FAIL_COUNT subtests (of $TEST_NUM) failed - see stderr"
117*640235e2SEnji Cooper}
118*640235e2SEnji Cooper
119*640235e2SEnji Cooperatf_test_case do_simple
120*640235e2SEnji Cooperdo_simple_head() {
12157718be8SEnji Cooper	atf_set "descr" "Basic tests for here documents"
12257718be8SEnji Cooper}
123*640235e2SEnji Cooperdo_simple_body() {
12457718be8SEnji Cooper	y=x
12557718be8SEnji Cooper
126*640235e2SEnji Cooper	reset 'simple'
127*640235e2SEnji Cooper	IFS=' 	'
128*640235e2SEnji Cooper	check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
129*640235e2SEnji Cooper	check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
13057718be8SEnji Cooper
131*640235e2SEnji Cooper	check "y=${y};"'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
132*640235e2SEnji Cooper			'text' 0
133*640235e2SEnji Cooper	check "y=${y};"'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
134*640235e2SEnji Cooper			'te${y}t' 0
135*640235e2SEnji Cooper	check "y=${y};"'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
136*640235e2SEnji Cooper			'te${y}t' 0
137*640235e2SEnji Cooper	check "y=${y};"'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x'  \
138*640235e2SEnji Cooper			'te${y}t' 0
13957718be8SEnji Cooper
140*640235e2SEnji Cooper	# check that quotes in the here doc survive and cause no problems
141*640235e2SEnji Cooper	check "cat <<EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
142*640235e2SEnji Cooper	check "cat <<\EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
143*640235e2SEnji Cooper	check "cat <<'EOF'${nl}te'xt${nl}EOF$nl" "te'xt" 0
144*640235e2SEnji Cooper	check "cat <<EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
145*640235e2SEnji Cooper	check "cat <<\EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
146*640235e2SEnji Cooper	check "cat <<'EOF'${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
147*640235e2SEnji Cooper	check "cat <<'EO'F${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
14857718be8SEnji Cooper
149*640235e2SEnji Cooper	check "y=${y};"'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' \
150*640235e2SEnji Cooper			'te'"'"'xt' 0
151*640235e2SEnji Cooper	check "y=${y};"'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' \
152*640235e2SEnji Cooper			'te'"''"'xt' 0
153*640235e2SEnji Cooper
154*640235e2SEnji Cooper	# note that the blocks of empty space in the following must
155*640235e2SEnji Cooper	# be entirely tab characters, no spaces.
156*640235e2SEnji Cooper
157*640235e2SEnji Cooper	check 'x=`cat <<EOF'"$nl	text${nl}EOF$nl"'`; echo "$x"' \
158*640235e2SEnji Cooper			'	text' 0
159*640235e2SEnji Cooper	check 'x=`cat <<-EOF'"$nl	text${nl}EOF$nl"'`; echo $x' \
160*640235e2SEnji Cooper			'text' 0
161*640235e2SEnji Cooper	check 'x=`cat <<-EOF'"${nl}text${nl}	EOF$nl"'`; echo $x' \
162*640235e2SEnji Cooper			'text' 0
163*640235e2SEnji Cooper	check 'x=`cat <<-\EOF'"$nl	text${nl}	EOF$nl"'`; echo $x' \
164*640235e2SEnji Cooper			'text' 0
165*640235e2SEnji Cooper	check 'x=`cat <<- "EOF"'"$nl	text${nl}EOF$nl"'`; echo $x' \
166*640235e2SEnji Cooper			'text' 0
167*640235e2SEnji Cooper	check 'x=`cat <<- '"'EOF'${nl}text${nl}	EOF$nl"'`; echo $x' \
168*640235e2SEnji Cooper			'text' 0
169*640235e2SEnji Cooper	results
170*640235e2SEnji Cooper}
171*640235e2SEnji Cooper
172*640235e2SEnji Cooperatf_test_case end_markers
173*640235e2SEnji Cooperend_markers_head() {
174*640235e2SEnji Cooper	atf_set "descr" "Tests for various end markers of here documents"
175*640235e2SEnji Cooper}
176*640235e2SEnji Cooperend_markers_body() {
177*640235e2SEnji Cooper
178*640235e2SEnji Cooper	reset 'end_markers'
179*640235e2SEnji Cooper	for end in EOF 1 \! '$$$' "string " a\\\ a\\\ \   '&' '' ' ' '  ' \
180*640235e2SEnji Cooper	    --STRING-- . '~~~' ')' '(' '#' '()' '(\)' '(\/)' '--' '\' '{' '}' \
181*640235e2SEnji CooperVERYVERYVERYVERYLONGLONGLONGin_fact_absurdly_LONG_LONG_HERE_DOCUMENT_TERMINATING_MARKER_THAT_goes_On_forever_and_ever_and_ever...
182*640235e2SEnji Cooper	do
183*640235e2SEnji Cooper		# check unquoted end markers
184*640235e2SEnji Cooper		case "${end}" in
185*640235e2SEnji Cooper		('' | *[' ()\$&#*~']* ) ;;	# skip unquoted endmark test for these
186*640235e2SEnji Cooper		(*)	check \
187*640235e2SEnji Cooper	'x=$(cat << '"${end}${nl}text${nl}${end}${nl}"'); printf %s "$x"' 'text' 0
188*640235e2SEnji Cooper			;;
189*640235e2SEnji Cooper		esac
190*640235e2SEnji Cooper
191*640235e2SEnji Cooper		# and quoted end markers
192*640235e2SEnji Cooper		check \
193*640235e2SEnji Cooper	'x=$(cat <<'"'${end}'${nl}text${nl}${end}${nl}"'); printf %s "$x"' 'text' 0
194*640235e2SEnji Cooper
195*640235e2SEnji Cooper		# and see what happens if we encounter "almost" an end marker
196*640235e2SEnji Cooper		case "${#end}" in
197*640235e2SEnji Cooper		(0|1)	;;		# too short to try truncation tests
198*640235e2SEnji Cooper		(*)	check \
199*640235e2SEnji Cooper   'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}${nl}${end}${nl}"'); printf %s "$x"' \
200*640235e2SEnji Cooper				"text ${end%?}" 0
201*640235e2SEnji Cooper			check \
202*640235e2SEnji Cooper   'x=$(cat <<'"'${end}'${nl}text${nl}${end#?}${nl}${end}${nl}"'); printf %s "$x"' \
203*640235e2SEnji Cooper				"text ${end#?}" 0
204*640235e2SEnji Cooper			check \
205*640235e2SEnji Cooper   'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}+${nl}${end}${nl}"');printf %s "$x"' \
206*640235e2SEnji Cooper				"text ${end%?}+" 0
207*640235e2SEnji Cooper			;;
208*640235e2SEnji Cooper		esac
209*640235e2SEnji Cooper
210*640235e2SEnji Cooper		# or something that is a little longer
211*640235e2SEnji Cooper		check \
212*640235e2SEnji Cooper   'x=$(cat <<'"'${end}'${nl}text${nl}${end}x${nl}${end}${nl}"'); printf %s "$x"' \
213*640235e2SEnji Cooper				"text ${end}x" 0
214*640235e2SEnji Cooper		check \
215*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}!${end}${nl}${end}${nl}"'); printf %s "$x"' \
216*640235e2SEnji Cooper				"text !${end}" 0
217*640235e2SEnji Cooper
218*640235e2SEnji Cooper		# or which does not begin at start of line
219*640235e2SEnji Cooper		check \
220*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl} ${end}${nl}${end}${nl}"'); printf %s "$x"' \
221*640235e2SEnji Cooper				"text  ${end}" 0
222*640235e2SEnji Cooper		check \
223*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}	${end}${nl}${end}${nl}"'); printf %s "$x"' \
224*640235e2SEnji Cooper				"text 	${end}" 0
225*640235e2SEnji Cooper
226*640235e2SEnji Cooper		# or end at end of line
227*640235e2SEnji Cooper		check \
228*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${end} ${nl}${end}${nl}"'); printf %s "$x"' \
229*640235e2SEnji Cooper				"text ${end} " 0
230*640235e2SEnji Cooper
231*640235e2SEnji Cooper		# or something that is correct much of the way, but then...
232*640235e2SEnji Cooper
233*640235e2SEnji Cooper		case "${#end}" in
234*640235e2SEnji Cooper		(0)	;;		# cannot test this one
235*640235e2SEnji Cooper		(1)	check \
236*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${end}${end}${nl}${end}${nl}"'); printf %s "$x"' \
237*640235e2SEnji Cooper				"text ${end}${end}" 0
238*640235e2SEnji Cooper			;;
239*640235e2SEnji Cooper		(2-7)	pfx="${end%?}"
240*640235e2SEnji Cooper			check \
241*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${end}${pfx}${nl}${end}${nl}"'); printf %s "$x"' \
242*640235e2SEnji Cooper				"text ${end}${pfx}" 0
243*640235e2SEnji Cooper			check \
244*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); printf %s "$x"' \
245*640235e2SEnji Cooper				"text ${pfx}${end}" 0
246*640235e2SEnji Cooper			;;
247*640235e2SEnji Cooper		(*)	pfx=${end%??????}; sfx=${end#??????}
248*640235e2SEnji Cooper			check \
249*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${end}${sfx}${nl}${end}${nl}"'); printf %s "$x"' \
250*640235e2SEnji Cooper				"text ${end}${sfx}" 0
251*640235e2SEnji Cooper			check \
252*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); printf %s "$x"' \
253*640235e2SEnji Cooper				"text ${pfx}${end}" 0
254*640235e2SEnji Cooper			check \
255*640235e2SEnji Cooper    'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${sfx}${nl}${end}${nl}"'); printf %s "$x"' \
256*640235e2SEnji Cooper				"text ${pfx}${sfx}" 0
257*640235e2SEnji Cooper			;;
258*640235e2SEnji Cooper		esac
259*640235e2SEnji Cooper	done
260*640235e2SEnji Cooper
261*640235e2SEnji Cooper	# Add striptabs tests (in similar way) here one day...
262*640235e2SEnji Cooper
263*640235e2SEnji Cooper	results
264*640235e2SEnji Cooper}
265*640235e2SEnji Cooper
266*640235e2SEnji Cooperatf_test_case incomplete
267*640235e2SEnji Cooperincomplete_head() {
268*640235e2SEnji Cooper	atf_set "descr" "Basic tests for incomplete here documents"
269*640235e2SEnji Cooper}
270*640235e2SEnji Cooperincomplete_body() {
271*640235e2SEnji Cooper	reset incomplete
272*640235e2SEnji Cooper
273*640235e2SEnji Cooper	check 'cat <<EOF' '' 2
274*640235e2SEnji Cooper	check 'cat <<- EOF' '' 2
275*640235e2SEnji Cooper	check 'cat <<\EOF' '' 2
276*640235e2SEnji Cooper	check 'cat <<- \EOF' '' 2
277*640235e2SEnji Cooper
278*640235e2SEnji Cooper	check 'cat <<EOF'"${nl}" '' 2
279*640235e2SEnji Cooper	check 'cat <<- EOF'"${nl}" '' 2
280*640235e2SEnji Cooper	check 'cat <<'"'EOF'${nl}" '' 2
281*640235e2SEnji Cooper	check 'cat <<- "EOF"'"${nl}" '' 2
282*640235e2SEnji Cooper
283*640235e2SEnji Cooper	check 'cat << EOF'"${nl}${nl}" '' 2
284*640235e2SEnji Cooper	check 'cat <<-EOF'"${nl}${nl}" '' 2
285*640235e2SEnji Cooper	check 'cat << '"'EOF'${nl}${nl}" '' 2
286*640235e2SEnji Cooper	check 'cat <<-"EOF"'"${nl}${nl}" '' 2
287*640235e2SEnji Cooper
288*640235e2SEnji Cooper	check 'cat << EOF'"${nl}"'line 1'"${nl}" '' 2
289*640235e2SEnji Cooper	check 'cat <<-EOF'"${nl}"'	line 1'"${nl}" '' 2
290*640235e2SEnji Cooper	check 'cat << EOF'"${nl}"'line 1'"${nl}"'	line 2'"${nl}" '' 2
291*640235e2SEnji Cooper	check 'cat <<-EOF'"${nl}"'	line 1'"${nl}"'line 2'"${nl}" '' 2
292*640235e2SEnji Cooper
293*640235e2SEnji Cooper	check 'cat << EOF'"${nl}line 1${nl}${nl}line3${nl}${nl}5!${nl}" '' 2
294*640235e2SEnji Cooper
295*640235e2SEnji Cooper	results
296*640235e2SEnji Cooper}
297*640235e2SEnji Cooper
298*640235e2SEnji Cooperatf_test_case lineends
299*640235e2SEnji Cooperlineends_head() {
300*640235e2SEnji Cooper	atf_set "descr" "Tests for line endings in here documents"
301*640235e2SEnji Cooper}
302*640235e2SEnji Cooperlineends_body() {
303*640235e2SEnji Cooper	reset lineends
304*640235e2SEnji Cooper
305*640235e2SEnji Cooper	# note that "check" removes newlines from stdout before comparing.
306*640235e2SEnji Cooper	# (they become blanks, provided there is something before & after)
307*640235e2SEnji Cooper
308*640235e2SEnji Cooper	check 'cat << \echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" '\' 0
309*640235e2SEnji Cooper	check 'cat <<  echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" 'echo' 0
310*640235e2SEnji Cooper	check 'cat << echo'"${nl}"'\\'"${nl}echo${nl}echo${nl}" '\' 0
311*640235e2SEnji Cooper
312*640235e2SEnji Cooper	check 'X=3; cat << ec\ho'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
313*640235e2SEnji Cooper		'$X\'  0
314*640235e2SEnji Cooper	check 'X=3; cat <<  echo'"${nl}"'$X'"${nl}echo${nl}echo${nl}" \
315*640235e2SEnji Cooper		'3'  0
316*640235e2SEnji Cooper	check 'X=3; cat <<  echo'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
317*640235e2SEnji Cooper		''  0
318*640235e2SEnji Cooper	check 'X=3; cat <<  echo'"${nl}"'${X}\'"${nl}echo${nl}echo${nl}" \
319*640235e2SEnji Cooper		'3echo'  0
320*640235e2SEnji Cooper	check 'X=3; cat <<  echo'"${nl}"'\$X\'"${nl}echo${nl}echo${nl}" \
321*640235e2SEnji Cooper		'$Xecho'  0
322*640235e2SEnji Cooper	check 'X=3; cat <<  echo'"${nl}"'\\$X \'"${nl}echo${nl}echo${nl}" \
323*640235e2SEnji Cooper		'\3 echo'  0
324*640235e2SEnji Cooper
325*640235e2SEnji Cooper	check \
326*640235e2SEnji Cooper  'cat << "echo"'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
327*640235e2SEnji Cooper		 'line1\ line2\'  0
328*640235e2SEnji Cooper	check \
329*640235e2SEnji Cooper	  'cat << echo'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
330*640235e2SEnji Cooper	  'line1line2echo'  0
331*640235e2SEnji Cooper
332*640235e2SEnji Cooper	results
333*640235e2SEnji Cooper}
334*640235e2SEnji Cooper
335*640235e2SEnji Cooperatf_test_case multiple
336*640235e2SEnji Coopermultiple_head() {
337*640235e2SEnji Cooper	atf_set "descr" "Tests for multiple here documents on one cmd line"
338*640235e2SEnji Cooper}
339*640235e2SEnji Coopermultiple_body() {
340*640235e2SEnji Cooper	reset multiple
341*640235e2SEnji Cooper
342*640235e2SEnji Cooper	check \
343*640235e2SEnji Cooper    "(cat ; cat <&3) <<EOF0 3<<EOF3${nl}STDIN${nl}EOF0${nl}-3-${nl}EOF3${nl}" \
344*640235e2SEnji Cooper		'STDIN -3-' 0
345*640235e2SEnji Cooper
346*640235e2SEnji Cooper	check "(read line; echo \"\$line\"; cat <<EOF1; echo \"\$line\") <<EOF2
347*640235e2SEnji CooperThe File
348*640235e2SEnji CooperEOF1
349*640235e2SEnji CooperThe Line
350*640235e2SEnji CooperEOF2
351*640235e2SEnji Cooper"			'The Line The File The Line' 0
352*640235e2SEnji Cooper
353*640235e2SEnji Cooper	check "(read line; echo \"\$line\"; cat <<EOF; echo \"\$line\") <<EOF
354*640235e2SEnji CooperThe File
355*640235e2SEnji CooperEOF
356*640235e2SEnji CooperThe Line
357*640235e2SEnji CooperEOF
358*640235e2SEnji Cooper"			'The Line The File The Line' 0
359*640235e2SEnji Cooper
360*640235e2SEnji Cooper	check "V=1; W=2; cat <<-1; cat <<2; cat <<- 3; cat <<'4';"' cat <<\5
361*640235e2SEnji Cooper		$V
362*640235e2SEnji Cooper		$W
363*640235e2SEnji Cooper		3
364*640235e2SEnji Cooper	4
365*640235e2SEnji Cooper	5
366*640235e2SEnji Cooper			1
367*640235e2SEnji Cooper2
368*640235e2SEnji Cooper	5
369*640235e2SEnji Cooper					4*$W+\$V
370*640235e2SEnji Cooper	3
371*640235e2SEnji Cooper$W
372*640235e2SEnji Cooper1
373*640235e2SEnji Cooper2
374*640235e2SEnji Cooper3
375*640235e2SEnji Cooper4
376*640235e2SEnji Cooper7+$V
377*640235e2SEnji Cooper$W+6
378*640235e2SEnji Cooper5
379*640235e2SEnji Cooper'			'1 2 3 4 5 5 4*2+$V $W 1 2 3 7+$V $W+6'	0
380*640235e2SEnji Cooper
381*640235e2SEnji Cooper	results
382*640235e2SEnji Cooper}
383*640235e2SEnji Cooper
384*640235e2SEnji Cooperatf_test_case nested
385*640235e2SEnji Coopernested_head() {
386*640235e2SEnji Cooper	atf_set "descr" "Tests for nested here documents for one cmd"
387*640235e2SEnji Cooper}
388*640235e2SEnji Coopernested_body() {
389*640235e2SEnji Cooper	reset nested
390*640235e2SEnji Cooper
391*640235e2SEnji Cooper	check \
392*640235e2SEnji Cooper'cat << EOF1'"${nl}"'$(cat << EOF2'"${nl}LINE${nl}EOF2${nl}"')'"${nl}EOF1${nl}"\
393*640235e2SEnji Cooper	'LINE' 0
394*640235e2SEnji Cooper
395*640235e2SEnji Cooper# This next one fails ... and correctly, so we will omit it (bad test)
396*640235e2SEnji Cooper# Reasoning is that the correct data "$(cat << EOF2)\nLINE\nEOF2\n" is
397*640235e2SEnji Cooper# collected for the outer (EOF1) heredoc, when that is parsed, it looks
398*640235e2SEnji Cooper# like
399*640235e2SEnji Cooper#	$(cat <<EOF2)
400*640235e2SEnji Cooper#	LINE
401*640235e2SEnji Cooper#	EOF2
402*640235e2SEnji Cooper# which looks like a good command - except it is being parsed in "heredoc"
403*640235e2SEnji Cooper# syntax, which means it is enclosed in double quotes, which means that
404*640235e2SEnji Cooper# the newline after the ')' in the first line is not a newline token, but
405*640235e2SEnji Cooper# just a character.  The EOF2 heredoc cannot start until after the next
406*640235e2SEnji Cooper# newline token, of which there are none here...  LINE and EOF2 are just
407*640235e2SEnji Cooper# more data in the outer EOF1 heredoc for its "cat" command to read & write.
408*640235e2SEnji Cooper#
409*640235e2SEnji Cooper# The previous sub-test works because there the \n comes inside the
410*640235e2SEnji Cooper# $( ), and in there, the outside quoting rules are suspended, and it
411*640235e2SEnji Cooper# all starts again - so that \n is a newline token, and the EOF2 heredoc
412*640235e2SEnji Cooper# is processed.
413*640235e2SEnji Cooper#
414*640235e2SEnji Cooper#	check \
415*640235e2SEnji Cooper#   'cat << EOF1'"${nl}"'$(cat << EOF2 )'"${nl}LINE${nl}EOF2${nl}EOF1${nl}" \
416*640235e2SEnji Cooper#	'LINE' 0
417*640235e2SEnji Cooper
418*640235e2SEnji Cooper	L='cat << EOF1'"${nl}"'LINE1$(cat << EOF2'"${nl}"
419*640235e2SEnji Cooper	L="${L}"'LINE2$(cat << EOF3'"${nl}"
420*640235e2SEnji Cooper	L="${L}"'LINE3$(cat << EOF4'"${nl}"
421*640235e2SEnji Cooper	L="${L}"'LINE4$(cat << EOF5'"${nl}"
422*640235e2SEnji Cooper	L="${L}LINE5${nl}EOF5${nl})4${nl}EOF4${nl})3${nl}"
423*640235e2SEnji Cooper	L="${L}EOF3${nl})2${nl}EOF2${nl})1${nl}EOF1${nl}"
424*640235e2SEnji Cooper
425*640235e2SEnji Cooper	# That mess is ...
426*640235e2SEnji Cooper	#
427*640235e2SEnji Cooper	#	cat <<EOF1
428*640235e2SEnji Cooper	#	LINE1$(cat << EOF2
429*640235e2SEnji Cooper	#	LINE2$(cat << EOF3
430*640235e2SEnji Cooper	#	LINE3$(cat << EOF4
431*640235e2SEnji Cooper	#	LINE4$(cat << EOF5
432*640235e2SEnji Cooper	#	LINE5
433*640235e2SEnji Cooper	#	EOF5
434*640235e2SEnji Cooper	#	)4
435*640235e2SEnji Cooper	#	EOF4
436*640235e2SEnji Cooper	#	)3
437*640235e2SEnji Cooper	#	EOF3
438*640235e2SEnji Cooper	#	)2
439*640235e2SEnji Cooper	#	EOF2
440*640235e2SEnji Cooper	#	)1
441*640235e2SEnji Cooper	#	EOF1
442*640235e2SEnji Cooper
443*640235e2SEnji Cooper	check "${L}" 'LINE1LINE2LINE3LINE4LINE54321' 0
444*640235e2SEnji Cooper
445*640235e2SEnji Cooper	results
446*640235e2SEnji Cooper}
447*640235e2SEnji Cooper
448*640235e2SEnji Cooperatf_test_case quoting
449*640235e2SEnji Cooperquoting_head() {
450*640235e2SEnji Cooper	atf_set "descr" "Tests for use of quotes inside here documents"
451*640235e2SEnji Cooper}
452*640235e2SEnji Cooperquoting_body() {
453*640235e2SEnji Cooper	reset quoting
454*640235e2SEnji Cooper
455*640235e2SEnji Cooper	check 'X=!; cat <<- E\0F
456*640235e2SEnji Cooper		<'\''"'\'' \\$X\$X  "'\''" \\>
457*640235e2SEnji Cooper	E0F
458*640235e2SEnji Cooper	'	'<'\''"'\'' \\$X\$X  "'\''" \\>'	0
459*640235e2SEnji Cooper
460*640235e2SEnji Cooper	check 'X=!; cat <<- E0F
461*640235e2SEnji Cooper		<'\''"'\'' \\$X\$X  "'\''" \\>
462*640235e2SEnji Cooper	E0F
463*640235e2SEnji Cooper	'	'<'\''"'\'' \!$X  "'\''" \>'	0
464*640235e2SEnji Cooper
465*640235e2SEnji Cooper	check 'cat <<- END
466*640235e2SEnji Cooper		$( echo "'\''" ) $( echo '\''"'\'' ) $( echo \\ )
467*640235e2SEnji Cooper	END
468*640235e2SEnji Cooper	'	"' \" \\"		0
469*640235e2SEnji Cooper
470*640235e2SEnji Cooper	check 'X=12345; Y="string1 line1?-line2"; Z=; unset W; cat <<-EOF
471*640235e2SEnji Cooper		${#X}${Z:-${Y}}${W+junk}${Y%%l*}${Y#*\?}
472*640235e2SEnji Cooper		"$Z"'\''$W'\'' ${Y%" "*} $(( X + 54321 ))
473*640235e2SEnji Cooper	EOF
474*640235e2SEnji Cooper	'	'5string1 line1?-line2string1 -line2 ""'\'\'' string1 66666' 0
475*640235e2SEnji Cooper
476*640235e2SEnji Cooper	results
477*640235e2SEnji Cooper}
478*640235e2SEnji Cooper
479*640235e2SEnji Cooperatf_test_case side_effects
480*640235e2SEnji Cooperside_effects_head() {
481*640235e2SEnji Cooper	atf_set "descr" "Tests how side effects in here documents are handled"
482*640235e2SEnji Cooper}
483*640235e2SEnji Cooperside_effects_body() {
484*640235e2SEnji Cooper
485*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'2\n1\n' -e empty ${TEST_SH} -c '
486*640235e2SEnji Cooper		unset X
487*640235e2SEnji Cooper		cat <<-EOF
488*640235e2SEnji Cooper		${X=2}
489*640235e2SEnji Cooper		EOF
490*640235e2SEnji Cooper		echo "${X-1}"
491*640235e2SEnji Cooper		'
492*640235e2SEnji Cooper}
493*640235e2SEnji Cooper
494*640235e2SEnji Cooperatf_test_case vicious
495*640235e2SEnji Coopervicious_head() {
496*640235e2SEnji Cooper	atf_set "descr" "Tests for obscure and obnoxious uses of here docs"
497*640235e2SEnji Cooper}
498*640235e2SEnji Coopervicious_body() {
499*640235e2SEnji Cooper	reset
500*640235e2SEnji Cooper
501*640235e2SEnji Cooper	cat <<- \END_SCRIPT > script
502*640235e2SEnji Cooper		cat <<ONE && cat \
503*640235e2SEnji Cooper		<<TWO
504*640235e2SEnji Cooper		a
505*640235e2SEnji Cooper		ONE
506*640235e2SEnji Cooper		b
507*640235e2SEnji Cooper		TWO
508*640235e2SEnji Cooper	END_SCRIPT
509*640235e2SEnji Cooper
510*640235e2SEnji Cooper	atf_check -s exit:0 -o inline:'a\nb\n' -e empty ${TEST_SH} script
511*640235e2SEnji Cooper
512*640235e2SEnji Cooper	# This next one is causing discussion currently (late Feb 2016)
513*640235e2SEnji Cooper	# amongst stds writers & implementors.   Consequently we
514*640235e2SEnji Cooper	# will not check what it produces.   The eventual result
515*640235e2SEnji Cooper	# seems unlikely to be what we currently output, which
516*640235e2SEnji Cooper	# is:
517*640235e2SEnji Cooper	#	A:echo line 1
518*640235e2SEnji Cooper	#	B:echo line 2)" && prefix DASH_CODE <<DASH_CODE
519*640235e2SEnji Cooper	#	B:echo line 3
520*640235e2SEnji Cooper	#	line 4
521*640235e2SEnji Cooper	#	line 5
522*640235e2SEnji Cooper	#
523*640235e2SEnji Cooper	# The likely intended output is ...
524*640235e2SEnji Cooper	#
525*640235e2SEnji Cooper	#	A:echo line 3
526*640235e2SEnji Cooper	#	B:echo line 1
527*640235e2SEnji Cooper	#	line 2
528*640235e2SEnji Cooper	#	DASH_CODE:echo line 4)"
529*640235e2SEnji Cooper	#	DASH_CODE:echo line 5
530*640235e2SEnji Cooper	#
531*640235e2SEnji Cooper	# The difference is explained by differing opinions on just
532*640235e2SEnji Cooper	# when processing of a here doc should start
533*640235e2SEnji Cooper
534*640235e2SEnji Cooper	cat <<- \END_SCRIPT > script
535*640235e2SEnji Cooper		prefix() { sed -e "s/^/$1:/"; }
536*640235e2SEnji Cooper		DASH_CODE() { :; }
537*640235e2SEnji Cooper
538*640235e2SEnji Cooper		prefix A <<XXX && echo "$(prefix B <<XXX
539*640235e2SEnji Cooper		echo line 1
540*640235e2SEnji Cooper		XXX
541*640235e2SEnji Cooper		echo line 2)" && prefix DASH_CODE <<DASH_CODE
542*640235e2SEnji Cooper		echo line 3
543*640235e2SEnji Cooper		XXX
544*640235e2SEnji Cooper		echo line 4)"
545*640235e2SEnji Cooper		echo line 5
546*640235e2SEnji Cooper		DASH_CODE
547*640235e2SEnji Cooper	END_SCRIPT
548*640235e2SEnji Cooper
549*640235e2SEnji Cooper	# we will just verify that the shell can parse the
550*640235e2SEnji Cooper	# script somehow, and doesn't fall over completely...
551*640235e2SEnji Cooper
552*640235e2SEnji Cooper	atf_check -s exit:0 -o ignore -e empty ${TEST_SH} script
55357718be8SEnji Cooper}
55457718be8SEnji Cooper
55557718be8SEnji Cooperatf_init_test_cases() {
556*640235e2SEnji Cooper	atf_add_test_case do_simple	# not worthy of a comment
557*640235e2SEnji Cooper	atf_add_test_case end_markers	# the mundane, the weird, the bizarre
558*640235e2SEnji Cooper	atf_add_test_case incomplete	# where the end marker isn't...
559*640235e2SEnji Cooper	atf_add_test_case lineends	# test weird line endings in heredocs
560*640235e2SEnji Cooper	atf_add_test_case multiple	# multiple << operators on one cmd
561*640235e2SEnji Cooper	atf_add_test_case nested	# here docs inside here docs
562*640235e2SEnji Cooper	atf_add_test_case quoting	# stuff quoted inside
563*640235e2SEnji Cooper	atf_add_test_case side_effects	# here docs that modify environment
564*640235e2SEnji Cooper	atf_add_test_case vicious	# evil test from the austin-l list...
56557718be8SEnji Cooper}
566