xref: /netbsd-src/tests/bin/sh/t_syntax.sh (revision 79548a514e9299d5ca947508f8a320cf370efbd8)
1*79548a51Sandvar# $NetBSD: t_syntax.sh,v 1.13 2023/12/28 20:04:10 andvar Exp $
279115595Skre#
379115595Skre# Copyright (c) 2017 The NetBSD Foundation, Inc.
479115595Skre# All rights reserved.
579115595Skre#
679115595Skre# Redistribution and use in source and binary forms, with or without
779115595Skre# modification, are permitted provided that the following conditions
879115595Skre# are met:
979115595Skre# 1. Redistributions of source code must retain the above copyright
1079115595Skre#    notice, this list of conditions and the following disclaimer.
1179115595Skre# 2. Redistributions in binary form must reproduce the above copyright
1279115595Skre#    notice, this list of conditions and the following disclaimer in the
1379115595Skre#    documentation and/or other materials provided with the distribution.
1479115595Skre#
1579115595Skre# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1679115595Skre# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1779115595Skre# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1879115595Skre# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
1979115595Skre# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2079115595Skre# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2179115595Skre# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2279115595Skre# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2379115595Skre# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2479115595Skre# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2579115595Skre# POSSIBILITY OF SUCH DAMAGE.
2679115595Skre#
2779115595Skre: ${TEST_SH:=/bin/sh}
2879115595Skre
2979115595Skre# This set of tests verifies various requirementgs relating to correct
3079115595Skre# (and incorrect) syntax of shell input
3179115595Skre#
3279115595Skre# There is no intent in these tests to verify correct operation
3379115595Skre# (though that sometimes cannot be separated from correct parsing.)
3479115595Skre# That is (or should be) verified elsewhere.
3579115595Skre#
3679115595Skre# Also, some very basic syntax is tested in almost every test
3779115595Skre# (they cannot work without basic parsing of elementary commands)
3879115595Skre# so that is also not explicitly tested here.
3979115595Skre#
4079115595Skre# Similarly word expansion, field splitting, redirection, all have
4179115595Skre# tests of their own (though we do test parsing of redirect ops).
4279115595Skre#
4379115595Skre# Note that in order to test the basic facilities, other shell operations
4479115595Skre# are used - a test failure here does not necessarily mean that the
4579115595Skre# operation intended to be tested is faulty, just that something is.
4679115595Skre
4779115595Skreatf_test_case a_basic_tokenisation
4879115595Skrea_basic_tokenisation_head() {
4979115595Skre	atf_set "descr" "Test the shell correctly finds various tokens"
5079115595Skre}
5179115595Skrea_basic_tokenisation_body() {
5279115595Skre	atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \
5379115595Skre		'set -- a b c; echo $#'
5479115595Skre	atf_check -s exit:0 -o 'inline:2\n' -e empty ${TEST_SH} -c \
5579115595Skre		'set -- a""b c; echo $#'
5679115595Skre	atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \
5779115595Skre		'set -- a"" b c; echo $#'
5879115595Skre	atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \
5979115595Skre		'set -- ""a b c\;; echo $#'
6079115595Skre
6179115595Skre	atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \
6279115595Skre		'set -- set -- c; echo $#'
6379115595Skre	atf_check -s exit:0 -o 'inline:1\n' -e empty ${TEST_SH} -c \
6479115595Skre		'set --;set -- c; echo $#'
6579115595Skre	atf_check -s exit:0 -o 'inline:1\n' -e empty ${TEST_SH} -c \
6679115595Skre		'set --&set -- c; echo $#'
6779115595Skre	atf_check -s exit:0 -o 'inline:1\n' -e empty ${TEST_SH} -c \
6879115595Skre		'set -- a b&&set -- c; echo $#'
6979115595Skre	atf_check -s exit:0 -o 'inline:2\n' -e empty ${TEST_SH} -c \
7079115595Skre		'set -- a b||set -- c; echo $#'
7179115595Skre}
7279115595Skre
7379115595Skreatf_test_case b_comments
7479115595Skreb_comments_head() {
7579115595Skre	atf_set "descr" "Test the shell correctly handles comments"
7679115595Skre}
7779115595Skreb_comments_body() {
7879115595Skre
7979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '#'
8079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '# exit 1'
8179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'true # exit 1'
8279115595Skre	atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c 'false # exit 0'
8379115595Skre
8479115595Skre	atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \
8579115595Skre		'echo foo # bar'
8679115595Skre	atf_check -s exit:0 -o 'inline:foo # bar\n' -e empty ${TEST_SH} -c \
8779115595Skre		'echo foo \# bar'
8879115595Skre	atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \
8979115595Skre		'echo foo; # echo bar'
9079115595Skre	atf_check -s exit:0 -o 'inline:foo#bar\n' -e empty ${TEST_SH} -c \
9179115595Skre		'echo foo#bar'
9279115595Skre	atf_check -s exit:0 -o 'inline:foo# bar\n' -e empty ${TEST_SH} -c \
9379115595Skre		'echo foo# bar'
9479115595Skre	atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \
9579115595Skre		'x=foo; echo ${x#bar}'
9679115595Skre
9779115595Skre	atf_check -s exit:0 -o 'inline:#\n' -e empty ${TEST_SH} -c \
9879115595Skre		'echo "#"'
9979115595Skre	atf_check -s exit:0 -o 'inline:#\n' -e empty ${TEST_SH} -c \
10079115595Skre		"echo '#'"
10179115595Skre	atf_check -s exit:0 -o 'inline:#\n' -e empty ${TEST_SH} -c \
10279115595Skre		'echo \#'
10379115595Skre	atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \
10479115595Skre		'echo "#"#'
10579115595Skre	atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \
10679115595Skre		"echo '#'#"
10779115595Skre	atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \
10879115595Skre		'echo \##'
10979115595Skre	atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \
11079115595Skre		'echo "#"# #"#"'
11179115595Skre	atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \
11279115595Skre		"echo '#'# #'#'"
11379115595Skre	atf_check -s exit:0 -o 'inline:##\n' -e empty ${TEST_SH} -c \
11479115595Skre		'echo \## #\#'
11579115595Skre
116d4ae1f8bSkre	cat <<-'DONE' |
117*79548a51Sandvar		# test comments do not provoke syntax errors !\
11879115595Skre		echo foo # ( { " hello
11979115595Skre		while : # that's forever
12079115595Skre		do	# the following command list
12179115595Skre			# starting with nothing ${unset?error}
12279115595Skre			break	# done loop terminate $( echo bar; exit 1 )
12379115595Skre		done #####################################################
12479115595Skre		# "hello
12579115595Skre		exit 0
12679115595Skre	DONE
127d4ae1f8bSkre		atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} ||
128d4ae1f8bSkre			atf_fail "ignoring comments"
12979115595Skre}
13079115595Skre
13179115595Skreatf_test_case c_line_wrapping
13279115595Skrec_line_wrapping_head() {
13379115595Skre	atf_set "descr" "check aspects of command line wrapping"
13479115595Skre}
13579115595Skrec_line_wrapping_body() {
13679115595Skre	atf_require_prog ls
13779115595Skre	atf_require_prog printf
13879115595Skre
139b1f04c11Skre	cat <<- 'DONE' | atf_check -s exit:0 -o ignore -e empty ${TEST_SH} -e ||
14079115595Skre		l\
14179115595Skre		s
14279115595Skre	DONE
143b1f04c11Skre		atf_fail "#1: ls wrapped fails"
14479115595Skre
145b1f04c11Skre	cat <<- 'DONE' | atf_check -s exit:7 -o empty -e empty ${TEST_SH} ||
14679115595Skre		e\
14779115595Skre		x\
14879115595Skre		it \
14979115595Skre		7
15079115595Skre	DONE
151b1f04c11Skre		atf_fail "#2: exit7 wrapped fails"
15279115595Skre
15379115595Skre	# Have to do this twice as cannot say "any exit code but 0 or 7" ...
15479115595Skre	cat <<- 'DONE' | atf_check -s not-exit:0 -o empty -e not-empty \
155b1f04c11Skre	    ${TEST_SH} ||
15679115595Skre		e\
15779115595Skre		x\
15879115595Skre		it\
15979115595Skre		7
16079115595Skre	DONE
161b1f04c11Skre		atf_fail "#3a: !exit(0||7) badly wrapped fails (0)"
16279115595Skre	cat <<- 'DONE' | atf_check -s not-exit:7 -o empty -e not-empty \
163b1f04c11Skre	    ${TEST_SH} ||
16479115595Skre		e\
16579115595Skre		x\
16679115595Skre		it\
16779115595Skre		7
16879115595Skre	DONE
169b1f04c11Skre		atf_fail "#3b: !exit(0||7) badly wrapped fails (7)"
17079115595Skre
171b1f04c11Skre	cat <<- 'DONE' | atf_check -s exit:0 -o empty -e empty  ${TEST_SH} ||
17279115595Skre		wh\
17379115595Skre		il\
17479115595Skre		e \
17579115595Skre		f\a\
17679115595Skre		\l\s\e
17779115595Skre		do
17879115595Skre		:\
17979115595Skre		;
18079115595Skre		done
18179115595Skre	DONE
182b1f04c11Skre		atf_fail "#4: wrapped while fails"
18379115595Skre
18479115595Skre	cat <<- 'DONE' | atf_check -s exit:0 -o inline:'hellohellohellohello' \
185b1f04c11Skre	    -e empty ${TEST_SH} ||
18679115595Skre		V\
18779115595Skre		AR=hel\
18879115595Skre		lo
18979115595Skre		unset U V1
19079115595Skre		pri\
19179115595Skre		ntf '%s' ${\
19279115595Skre		VAR\
19379115595Skre		}
19479115595Skre		p\
19579115595Skre		r\
19679115595Skre		i\
19779115595Skre		n\
19879115595Skre		t\
19979115595Skre		f\
20079115595Skre		 \
20179115595Skre		'%s' \
20279115595Skre		$\
20379115595Skre		{\
20479115595Skre		V\
20579115595Skre		A\
20679115595Skre		R}
20779115595Skre		printf '%s' ${U\
20879115595Skre		-\
20979115595Skre		"$\
21079115595Skre		{V\
21179115595Skre		1:\
21279115595Skre		=$\
21379115595Skre		{V\
21479115595Skre		AR+\
21579115595Skre		${V\
21679115595Skre		AR}\
21779115595Skre		}\
218e045f926Skre		}"}
21979115595Skre		printf '%s' ${V\
22079115595Skre		1?V1\
22179115595Skre		 \
22279115595Skre		FAIL}
22379115595Skre	DONE
224b1f04c11Skre		atf_fail "#5: wrapped var expansions fails"
225e045f926Skre
226b1f04c11Skre	cat <<- 'DONE' | atf_check -s exit:0 -o inline:'2\n' ${TEST_SH} ||
22779115595Skre		l\
22879115595Skre		s=7 bi\
22979115595Skre		n\
23079115595Skre		=\
23179115595Skre		3
23279115595Skre		echo $(\
23379115595Skre		( ls /bin )\
23479115595Skre		)
23579115595Skre	DONE
236b1f04c11Skre		atf_fail "#6: wrapped command substitution fails"
237e045f926Skre
238e045f926Skre	# Inspired by src/etc/MAKEDEV.tmpl failure with (broken)
239e045f926Skre	# sh LINENO code...  avoid it happening again...
240e045f926Skre	for VARS in 1:0:0:0 0:1:0:0 0:0:1:0 0:0:0:1 \
241e045f926Skre		    1:0:0:1 1:0:1:0 1:1:0:0 0:1:1:0 \
242e045f926Skre		    0:0:0:0 1:1:0:1 0:1:1:1 1:1:1:1
243e045f926Skre	do
244e045f926Skre		eval $(
245e045f926Skre			IFS=:
246e045f926Skre			set -- $VARS
247e045f926Skre			test $(( $1 + $2 + $3 + $4 )) -eq 1 &&
248e045f926Skre				R=OK || R=BAD
249e045f926Skre			printf "R=%s;" $R
250e045f926Skre			for v in a b c d
251e045f926Skre			do
252e045f926Skre				case $1 in
253e045f926Skre				(0)	printf "export %s=false;" $v;;
254e045f926Skre				(1)	printf "export %s=true;"  $v;;
255e045f926Skre				esac
256e045f926Skre				shift
257e045f926Skre			done
258e045f926Skre		)
259e045f926Skre
260b1f04c11Skre		cat <<- 'DONE' |
261e045f926Skre			case $(( $($a && echo 1 || echo 0) + \
262e045f926Skre				 $($b && echo 1 || echo 0) + \
263e045f926Skre				 $($c && echo 1 || echo 0) + \
264e045f926Skre				 $($d && echo 1 || echo 0) ))
265e045f926Skre			in
266e045f926Skre			(1)	printf OK ;;
267e045f926Skre			(*)	printf BAD ;;
268e045f926Skre			esac
269e045f926Skre		DONE
270b1f04c11Skre			atf_check -s exit:0 -o inline:"${R}" ${TEST_SH} ||
271b1f04c11Skre			atf_fail "#7 (${VARS}): wrapped arith fails"
272e045f926Skre	done
273e045f926Skre
274e045f926Skre	# inspired by pkgsrc/pkgtools/cwrappers :: libnbcompat/configure
275327a7bf9Skre	# failure with (broken) sh LINENO code .. avoid recurrence
276e045f926Skre	# This test would have failed.
277b1f04c11Skre	cat <<- 'DONE' | atf_check -s exit:0 -o inline:'/tmp\n' ${TEST_SH} ||
278e045f926Skre		dn=/tmp/foo
279e045f926Skre
280e045f926Skre		D=`dirname -- "${dn}" ||
281e045f926Skre		expr	X"${dn}" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
282e045f926Skre			X"${dn}" : 'X\(//\)[^/]' \| \
283e045f926Skre			X"${dn}" : 'X\(//\)$' \| \
284e045f926Skre			X"${dn}" : 'X\(/\)' \| . 2>/dev/null ||
285e045f926Skre		echo X"${dn}" |
286e045f926Skre		    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
287e045f926Skre			    s//\1/
288e045f926Skre			    q
289e045f926Skre			  }
290e045f926Skre			  /^X\(\/\/\)[^/].*/{
291e045f926Skre			    s//\1/
292e045f926Skre			    q
293e045f926Skre			  }
294e045f926Skre			  /^X\(\/\/\)$/{
295e045f926Skre			    s//\1/
296e045f926Skre			    q
297e045f926Skre			  }
298e045f926Skre			  /^X\(\/\).*/{
299e045f926Skre			    s//\1/
300e045f926Skre			    q
301e045f926Skre			  }
302e045f926Skre			  s/.*/./; q'`
303e045f926Skre
304e045f926Skre		echo "${D}"
305e045f926Skre	DONE
306b1f04c11Skre		atf_fail "#8:  cwrappers/LINENO bug test failed"
307b1f04c11Skre
308e045f926Skre	return 0
30979115595Skre}
31079115595Skre
311327a7bf9Skreatf_test_case d_cstrings
312327a7bf9Skred_cstrings_head() {
313327a7bf9Skre	atf_set "descr" "Check processing of $' ' quoting (C style strings)"
314327a7bf9Skre}
315327a7bf9Skred_cstrings_body() {
316327a7bf9Skre	unset ENV
3179985dad5Skre
318327a7bf9Skre	if ! ${TEST_SH} -c ": \$'abc'" ||
319327a7bf9Skre	     test $( ${TEST_SH} -c "printf %s \$'abc'" ) != abc
320327a7bf9Skre	then
321327a7bf9Skre		atf_skip "\$'...' (C style quoted strings) not supported"
322327a7bf9Skre	fi
323327a7bf9Skre
324327a7bf9Skre	# simple stuff
325327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'abc\tdef\n' ${TEST_SH} -c \
326327a7bf9Skre		"printf '%s\\n' \$'abc\tdef'"
327327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'abc\tdef\n' ${TEST_SH} -c \
328327a7bf9Skre		"printf '%s\\n' \$'abc\011def'"
329327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'abc\tdef\n' ${TEST_SH} -c \
330327a7bf9Skre		"printf '%s\\n' \$'abc\x09'def"
331327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'abc$def\n' ${TEST_SH} -c \
332327a7bf9Skre		"def=xyz; printf '%s\\n' \$'abc\$def'"
333327a7bf9Skre
334327a7bf9Skre	# control chars (\c) and unicode \u
335327a7bf9Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
336327a7bf9Skre		"test \$'\\1-\\2-\\3' = \$'\\ca-\\cb-\\cc'"
337327a7bf9Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
338327a7bf9Skre		"test \$'\\r-\\n-\\f' = \$'\\cm-\\cj-\\cl'"
339327a7bf9Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
3405f02c8e9Skre		"unset LC_ALL; export LC_CTYPE=en_AU.UTF-8;
3415f02c8e9Skre		test \$'\\u0123' = \$'\\304\\243'"
342327a7bf9Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
343327a7bf9Skre		"test \$'\\u0123' = \$'\\xC4\\xA3'"
344327a7bf9Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
345327a7bf9Skre		"test \$'\\c\\\\' = \$'\\x1C'"
346327a7bf9Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
347327a7bf9Skre		"test \$'\\c[\\c]\\c^\\c_\\c?' = \$'\\x1B\\x1D\\x1E\\x1F\\x7F'"
348327a7bf9Skre
349327a7bf9Skre	# all the \X sequences for a single char X (ie: not hex/octal/unicode)
350327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'\n\r\t\n' \
351327a7bf9Skre		${TEST_SH} -c "printf '%s\\n' \$'\\a\\b\\e\\f\\n\\r\\t\\v'"
352327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'\n\r\t\n' \
353327a7bf9Skre	   ${TEST_SH} -c "printf '%s\\n' \$'\\cG\\cH\\x1b\\cl\\cJ\\cm\\cI\\ck'"
354327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:"'"'"\\\n' \
355327a7bf9Skre		${TEST_SH} -c "printf '%s\\n' \$'\\'\\\"\\\\'"
356327a7bf9Skre
357327a7bf9Skre	# various invalid $'...' sequences
358327a7bf9Skre	atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \
359327a7bf9Skre		": \$'\\q'"
360327a7bf9Skre	atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \
361327a7bf9Skre		": \$'\\c\\q'"
362327a7bf9Skre	atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \
363327a7bf9Skre		": \$'\\uDEFF'"
364327a7bf9Skre	atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \
365327a7bf9Skre		": \$'abcd"
366327a7bf9Skre	atf_check -s not-exit:0 -e not-empty -o ignore ${TEST_SH} -c \
367327a7bf9Skre		": \$'abcd\\"
368327a7bf9Skre
3695f02c8e9Skre	# anything that generates \0 ends the $'...' immediately
3705f02c8e9Skre	atf_check -s exit:0 -e empty -o inline:'aAaA' ${TEST_SH} -c \
3715f02c8e9Skre		"printf '%s' \$'a\\0x'\$'A\\x00X'\$'a\\c@x'\$'A\\u0000X'"
372327a7bf9Skre
373327a7bf9Skre	# \newline in a $'...' is dropped (just like in "" strings)
374327a7bf9Skre	atf_check -s exit:0 -e empty -o inline:'abcdef' ${TEST_SH} -c \
375327a7bf9Skre"printf '%s' \$'abc\\
376327a7bf9Skredef'"
3779985dad5Skre	# but a normal newline in a $'...' is just a newline
3789985dad5Skre	atf_check -s exit:0 -e empty -o inline:'abc\ndef' ${TEST_SH} -c \
3799985dad5Skre"printf '%s' \$'abc
3809985dad5Skredef'"
3819985dad5Skre	# and should work when elided line wrap occurs between $ and '
3829985dad5Skre	atf_check -s exit:0 -e empty -o inline:'abc\ndef' ${TEST_SH} -c \
3839985dad5Skre"printf '%s' \$\\
3849985dad5Skre'abc\\ndef'"
3859985dad5Skre
3869985dad5Skre	# $'...' only works when the $ is unquoted.
3879985dad5Skre	atf_check -s exit:0 -e empty -o inline:"abc\$'def'g" ${TEST_SH} -c \
3889985dad5Skre		"printf '%s' \"abc\$'def'g\""
3899985dad5Skre	atf_check -s exit:0 -e empty -o inline:'abc$defg' ${TEST_SH} -c \
3909985dad5Skre		"printf '%s' abc\\\$'def'g"
3919985dad5Skre	atf_check -s exit:0 -e empty -o inline:'abc$def' ${TEST_SH} -c \
3929985dad5Skre		"printf '%s' abc'\$'def"
393327a7bf9Skre}
394327a7bf9Skre
395327a7bf9Skreatf_test_case f_redirects
396327a7bf9Skref_redirects_head() {
39779115595Skre	atf_set "descr" "Check parsing of redirect operators"
39879115595Skre}
399327a7bf9Skref_redirects_body() {
40079115595Skre
40179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
40279115595Skre		'>/dev/null'
40379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
40479115595Skre		'</dev/null'
40579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
40679115595Skre		'>>/dev/null'
40779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
40879115595Skre		'<>/dev/null'
40979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
41079115595Skre		'</dev/null>/dev/null'
41179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
41279115595Skre		'>|/dev/null'
41379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
41479115595Skre		'>/dev/null>/dev/null>/dev/null'
41579115595Skre
416a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
41779115595Skre		'echo hello >/dev/null'
418a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
41979115595Skre		'echo >/dev/null hello'
420a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
42179115595Skre		'>/dev/null echo hello'
422a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
42379115595Skre		'echo hello >/dev/null world'
424a2385816Skre	atf_check -s exit:0 -o 'inline:hello world\n' -e empty ${TEST_SH} -c \
42579115595Skre		'echo hello </dev/null world'
42679115595Skre
427a2385816Skre	atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \
42879115595Skre		'echo hello </dev/null'
429a2385816Skre	atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \
43079115595Skre		'echo hello 3</dev/null'
431a2385816Skre	atf_check -s exit:0 -o 'inline:hello 3\n' -e empty ${TEST_SH} -c \
43279115595Skre		'echo hello 3 </dev/null'
433a2385816Skre	atf_check -s exit:0 -o 'inline:hello 3\n' -e empty ${TEST_SH} -c \
43479115595Skre		'echo hello \3</dev/null'
435a2385816Skre	atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \
43679115595Skre		'echo hello</dev/null'
437a2385816Skre	atf_check -s exit:0 -o 'inline:3\n' -e empty ${TEST_SH} -c \
43879115595Skre		'hello=3; echo ${hello}</dev/null'
43979115595Skre
440a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
44179115595Skre		'2>&1'
442a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
44379115595Skre		'2>& 1'
444a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
44579115595Skre		'FD=1; 2>&"${FD}"'
446a2385816Skre	atf_check -s exit:0 -o 'inline:hello\n' -e empty ${TEST_SH} -c \
44779115595Skre		'FD=1; echo hello 2>&"${FD}" >&2'
44879115595Skre
449a2385816Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
45079115595Skre		'2>&- 3<&- 4>&-'
45179115595Skre
45279115595Skre	return 0
45379115595Skre}
45479115595Skre
455327a7bf9Skreatf_test_case g_variable_syntax
456327a7bf9Skreg_variable_syntax_head() {
45779115595Skre	atf_set "descr" "Check that var names of all legal forms work"
45879115595Skre}
459327a7bf9Skreg_variable_syntax_body() {
46079115595Skre	# don't test _ as a variable, it can be "unusual"
46179115595Skre	for vname in a ab _a _9 a123 a_1_2_3 __ ___ ____ __1__ _0 \
46279115595Skre	    A AA AAA AaBb _A_a A_a_ a1_ abc_123 ab_12_cd_ef_34_99 \
46379115595Skre	    abcdefghijklmnopqrstuvwzyz ABCDEFGHIJKLMNOPQRSTUVWXYZ_ \
4648b5ee9a5Skre	    A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all \
4658b5ee9a5Skre	    Then_Make_it_Even_Longer_by_Multiplying_it___A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all__A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all__A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all__A_VERY_LONG_VARIABLE_NAME_that_is_probably_longer_than_most_used_in_the_average_shell_script_already_about_100_chars_in_this_one_but_there_is_not_supposed_to_be_any_limit_on_the_length_at_all \
4668b5ee9a5Skre	    xyzzy __0123454321__ _0_1_2_3_4_5_6_7_8_9_ ABBA X_ Y__ Z___ \
46779115595Skre	    _____________________________________________________________
46879115595Skre	do
46979115595Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
47079115595Skre			"unset ${vname}"
47179115595Skre		atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -c \
47279115595Skre			"unset ${vname}; printf %s \${${vname}-OK}"
47379115595Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
47479115595Skre			"${vname}=GOOD; printf %s \${${vname}-OK}"
47579115595Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
47679115595Skre			"${vname}=GOOD; printf %s \$${vname}"
47779115595Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
47879115595Skre			"unset ${vname};${vname}=GOOD;printf %s \${${vname}-OK}"
47979115595Skre		atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -c \
48079115595Skre			"${vname}=GOOD;unset ${vname};printf %s \${${vname}-OK}"
48179115595Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
48279115595Skre			"${vname}=GOOD; unset ${vname}x; printf %s \$${vname}"
48379115595Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
48479115595Skre			"unset ${vname}x; ${vname}=GOOD; printf %s \$${vname}x"
4858b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
4868b5ee9a5Skre			"${vname}=GOOD; ${vname}_=BAD; printf %s \$${vname}"
4878b5ee9a5Skre
4888b5ee9a5Skre		case "${vname}" in
4898b5ee9a5Skre		?)	continue;;
4908b5ee9a5Skre		esac
4918b5ee9a5Skre
4928b5ee9a5Skre		# The following tests do not work for 1 char var names.
4938b5ee9a5Skre		# hence the check and "continue" above to skip the remaining
4948b5ee9a5Skre		# tests for that case
4958b5ee9a5Skre
4968b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
4978b5ee9a5Skre			"${vname}=GOOD; unset ${vname%?}; printf %s \$${vname}"
4988b5ee9a5Skre
4998b5ee9a5Skre		# (this next would work, but becomes just a duplicate of
5008b5ee9a5Skre		# an earlier test, so is pointless for 1 ch names)
5018b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
5028b5ee9a5Skre	"${vname}=GOOD; unset ${vname}x ${vname%?}; printf %s \$${vname}"
5038b5ee9a5Skre
5048b5ee9a5Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
5058b5ee9a5Skre			"unset ${vname%?};${vname}=GOOD; printf %s \$${vname%?}"
5068b5ee9a5Skre
5078b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
5088b5ee9a5Skre			"${vname}=GOOD; ${vname%?}=BAD; printf %s \$${vname}"
5098b5ee9a5Skre
5108b5ee9a5Skre		# all the remaining tests require the 2nd char of the
5118b5ee9a5Skre		# variable name to be a legal first character.  That
5128b5ee9a5Skre		# is, not a digit, so skip the rest if we have a digit
5138b5ee9a5Skre		# second...
5148b5ee9a5Skre		case "${vname}" in
5158b5ee9a5Skre		?[0-9]*)	continue;;
5168b5ee9a5Skre		esac
5178b5ee9a5Skre
5188b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
5198b5ee9a5Skre			"${vname}=GOOD; unset ${vname#?}; printf %s \$${vname}"
5208b5ee9a5Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
5218b5ee9a5Skre			"unset ${vname#?};${vname}=GOOD; printf %s \$${vname#?}"
5228b5ee9a5Skre
5238b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
5248b5ee9a5Skre			"${vname}=GOOD; ${vname#?}=BAD; printf %s \$${vname}"
5258b5ee9a5Skre
5268b5ee9a5Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
5278b5ee9a5Skre			"unset ${vname%?} ${vname#?} ${vname}x; ${vname}=GOOD;
5288b5ee9a5Skre			printf %s \$${vname%?}\$${vname#?}\$${vname}x"
5298b5ee9a5Skre
5308b5ee9a5Skre		atf_check -s exit:0 -o match:GOOD -e empty ${TEST_SH} -c \
5318b5ee9a5Skre			"${vname}=GOOD; ${vname%?}=BAD; ${vname}_=BAD;
5328b5ee9a5Skre			${vname#?}=BAD; printf %s \$${vname}"
53379115595Skre	done
53479115595Skre
53579115595Skre	# don't test '.' in var names, some shells permit that (in ${} anyway)
53679115595Skre	# this test also cannot check for embedded - + ? = : % or #
53779115595Skre	for vname in ,x -p +h :def 0_1 'x*x' '()' '"' "'" 'a b c' '?!' ';'
53879115595Skre	do
53979115595Skre		atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
54079115595Skre			"echo \${${vname}}"
54179115595Skre	done
54279115595Skre
54379115595Skre	for vname in ,x -p +h :def 0_1 'x*x' '()' '"' "'" 'a b c' x,y,z '?!' \
54479115595Skre	    ';' a-b a+b 'a?b' 'a:b' 'a%b' 'a#b' 0 1 99 @ '*' '!' '?'
54579115595Skre	do
54679115595Skre		# failure modes will differ, but they should all fail somehow
54779115595Skre		atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
54879115595Skre			"${vname}="
54979115595Skre	done
55079115595Skre
55179115595Skre}
55279115595Skre
553327a7bf9Skreatf_test_case h_var_assign
554327a7bf9Skreh_var_assign_head() {
55579115595Skre	atf_set "descr" "Check var assignments "
55679115595Skre}
557327a7bf9Skreh_var_assign_body() {
55879115595Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
55979115595Skre		'a=b'
56079115595Skre	atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
56179115595Skre		'\a=b'
56279115595Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
56379115595Skre		'a=b c=d'
56479115595Skre	atf_check -s exit:0 -e empty -o 'inline:e=f\n' ${TEST_SH} -c \
56579115595Skre		'a=b c=d echo e=f'
56679115595Skre	atf_check -s exit:0 -e empty -o 'inline:e=f\n' ${TEST_SH} -c \
56779115595Skre		'a=b 2>/dev/null c=d </dev/null echo e=f'
56879115595Skre
56979115595Skre	# We need to make sure that we do not accidentally
57079115595Skre	# find a command called 'a=b' ...
57179115595Skre
57279115595Skre	for d in /foo /foo/bar /not-dir /no/such/directory '/!!!' \
57379115595Skre		'/-/--/#' '/"/""/"""' -
57479115595Skre	do
57579115595Skre		test -d "${d}" || break
57679115595Skre	done
57779115595Skre	test "${#d}" -gt 1 || atf-skip 'Wacky directories seem to exist!'
57879115595Skre
57979115595Skre	atf_check -s exit:0 -e empty -o empty ${TEST_SH} -c \
58079115595Skre		"PATH='${d}';"'a=\b'
58179115595Skre	atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
58279115595Skre		"PATH='${d}';"'a\=b'
58379115595Skre	atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
58479115595Skre		"PATH='${d}';"'\a=b'
58579115595Skre	atf_check -s not-exit:0 -e not-empty -o empty ${TEST_SH} -c \
58679115595Skre		"PATH='${d}';"'X=; c=d ${X} a=b'
58779115595Skre}
58879115595Skre
58979115595Skreatf_test_case i_pipelines
59079115595Skrei_pipelines_head() {
59179115595Skre	atf_set "descr" "Check pipelines"
59279115595Skre}
59379115595Skrei_pipelines_body() {
59479115595Skre
59579115595Skre	cmd='printf "%s\n" foo'
59679115595Skre	for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
59779115595Skre	do
59879115595Skre		atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \
59979115595Skre			"${cmd}"
60079115595Skre		cmd="${cmd} | cat"
60179115595Skre	done
60279115595Skre
60379115595Skre	cmd='printf "%s\n" foo'
60479115595Skre	for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
60579115595Skre	do
60679115595Skre		atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \
60779115595Skre			"${cmd}"
60879115595Skre		cmd="${cmd} |
60979115595Skre		cat"
61079115595Skre	done
61179115595Skre
61279115595Skre	cmd='printf "%s\n" foo'
61379115595Skre	for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
61479115595Skre	do
61579115595Skre		atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \
61679115595Skre			"${cmd}"
61779115595Skre		cmd="${cmd} |
61879115595Skre
61979115595Skre
62079115595Skre
62179115595Skre
62279115595Skre		cat"
62379115595Skre	done
62479115595Skre
62579115595Skre	cmd='! printf "%s\n" foo'
62679115595Skre	for n in 1 2 3 4 5 6 7 8 9 10
62779115595Skre	do
62879115595Skre		atf_check -s exit:1 -o inline:'foo\n' -e empty ${TEST_SH} -c \
62979115595Skre			"${cmd}"
63079115595Skre		cmd="${cmd} | cat"
63179115595Skre	done
63279115595Skre
63379115595Skre	cmd='exec 4>&2 3<&0; printf "%s\n" foo'
63479115595Skre	for n in 1 2 3
63579115595Skre	do
63679115595Skre	    pfx=
63779115595Skre	    for xtra in 'x=y' 'a=b' '6>&1' '5<&3'
63879115595Skre	    do
63979115595Skre		atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \
64079115595Skre			"${cmd} | ${xtra} cat"
64179115595Skre
64279115595Skre		atf_check -s exit:0 -o inline:'foo\n' -e empty ${TEST_SH} -c \
64379115595Skre			"${cmd} | ${pfx} cat"
64479115595Skre
64579115595Skre		pfx="${pfx} ${xtra}"
64679115595Skre	    done
64779115595Skre	    cmd="${cmd} | ${pfx} cat"
64879115595Skre	done
64979115595Skre
65079115595Skre	# pipelines are not required to contain commands ...
65179115595Skre	# they don't do anything useful (at all) but the syntax is legal
65279115595Skre	base='4>&2'; cmd="${base}"
65379115595Skre	for pipe in 'a=b' '3<&0' '>>/dev/null' 'a= b= c=' '${x}' 'cat'
65479115595Skre	do
65579115595Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
65679115595Skre			"${base} | ${pipe}"
65779115595Skre
65879115595Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
65979115595Skre			"${cmd} | ${pipe}"
66079115595Skre
66179115595Skre		cmd="${cmd} | ${pipe}"
66279115595Skre	done
66379115595Skre
66479115595Skre	# but the command cannot be empty, or a reserved word used improperly
66579115595Skre	base='printf "%s\n" foo'; cmd="${base}"
66679115595Skre	for pipe in '' do done then else fi esac
66779115595Skre	do
66879115595Skre		atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
66979115595Skre			"${base} | ${pipe}"
67079115595Skre
67179115595Skre		atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
67279115595Skre			"${pipe} | ${base}"
67379115595Skre
67479115595Skre		atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
67579115595Skre			"${cmd} | ${pipe}"
67679115595Skre
67779115595Skre		cmd="${cmd} | ${pipe}"
67879115595Skre	done
67979115595Skre}
68079115595Skre
68179115595Skreatf_test_case j_and_or_lists
68279115595Skrej_and_or_lists_head() {
68379115595Skre	atf_set "descr" "Check && and || command lists"
68479115595Skre}
68579115595Skrej_and_or_lists_body() {
68679115595Skre	and=true
68779115595Skre	or=false
68879115595Skre	and_or=false
68979115595Skre	for i in 1 2 3 4 5 6 7 8 9 10
69079115595Skre	do
69179115595Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
69279115595Skre			"${and}"
69379115595Skre
69479115595Skre		atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
69579115595Skre			"${or}"
69679115595Skre
69779115595Skre		atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
69879115595Skre			"${and_or}"
69979115595Skre
70079115595Skre		and="${and} && true"
70179115595Skre		or="${or} || false"
70279115595Skre		and_or="${and_or} || true && false"
70379115595Skre	done
70479115595Skre
70579115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
70679115595Skre		'true &&'
70779115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
70879115595Skre		'&& true'
70979115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
71079115595Skre		'|| true'
71179115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
71279115595Skre		'true ||'
71379115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
71479115595Skre		'true || && false'
71579115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
71679115595Skre		'false || && true'
71779115595Skre
71879115595Skre	cmd='printf "%s" foo | cat | cat>/dev/null'
71979115595Skre	line="${cmd}"
72079115595Skre	for i in 1 2 3 4
72179115595Skre	do
72279115595Skre		line="${line} && ! ${cmd} || ${cmd}"
72379115595Skre
72479115595Skre		atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
72579115595Skre			"${line}"
72679115595Skre	done
72779115595Skre
72879115595Skre}
72979115595Skre
73079115595Skreatf_test_case k_lists
73179115595Skrek_lists_head() {
73279115595Skre	atf_set "descr" "Check ; command lists"
73379115595Skre}
73479115595Skrek_lists_body() {
73579115595Skre	line=
73679115595Skre	for N in 1 2 3 4
73779115595Skre	do
73879115595Skre		for cmd in \
73979115595Skre			true false : 'cat</dev/null>/dev/null' x=3 'exec 4>&-'
74079115595Skre		do
74179115595Skre			line="${line}${line:+;}${cmd}"
74279115595Skre			atf_check -s exit:0 -o 'inline:hello\nworld\n' \
74379115595Skre				-e empty ${TEST_SH} -c \
74479115595Skre					"echo hello; ${line}; echo world"
74579115595Skre			atf_check -s exit:0 -o 'inline:hello\nworld\n' \
74679115595Skre				-e empty ${TEST_SH} -c \
74779115595Skre					"echo hello; ${line}; echo world;"
74879115595Skre		done
74979115595Skre	done
75079115595Skre
75179115595Skre	for cmd in ';' ';;' 'false ;; true' 'false; ;true' '; true'
75279115595Skre	do
75379115595Skre		atf_check -s not-exit:0 -o ignore -e not-empty \
75479115595Skre			${TEST_SH} -c "${cmd}"
75579115595Skre	done
75679115595Skre}
75779115595Skre
75879115595Skreatf_test_case l_async_lists
75979115595Skrel_async_lists_head() {
76079115595Skre	atf_set "descr" "Check & command lists"
76179115595Skre}
76279115595Skrel_async_lists_body() {
76379115595Skre	line=
76479115595Skre	for N in 1 2 3 4
76579115595Skre	do
76679115595Skre		for cmd in \
76779115595Skre			true false : 'cat</dev/null>/dev/null' x=3 'exec 4>&-'
76879115595Skre		do
76979115595Skre			line="${line:+${line}&}${cmd}"
77079115595Skre			atf_check -s exit:0 -o 'inline:hello\nworld\n' \
77179115595Skre				-e empty ${TEST_SH} -c \
77279115595Skre					"echo hello; ${line}& echo world"
77379115595Skre			atf_check -s exit:0 -o 'inline:hello\nworld\n' \
77479115595Skre				-e empty ${TEST_SH} -c \
77579115595Skre					"echo hello; ${line}& echo world"
77679115595Skre		done
77779115595Skre	done
77879115595Skre
77979115595Skre	for cmd in '&' ';&' '&;'  '& true' 'false& &true'
78079115595Skre	do
78179115595Skre		atf_check -s not-exit:0 -o ignore -e not-empty \
78279115595Skre			${TEST_SH} -c "${cmd}"
78379115595Skre	done
78479115595Skre}
78579115595Skre
78679115595Skreatf_test_case m_compound_lists
78779115595Skrem_compound_lists_head() {
78879115595Skre	atf_set "descr" "Check subshells () and { ;} command grouping"
78979115595Skre}
79079115595Skrem_compound_lists_body() {
79179115595Skre	# Note: (( is an unspecified (reserved) operator, don't use it...
79279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
79379115595Skre		'( true )'
79479115595Skre	atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
79579115595Skre		'( false )'
79679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
79779115595Skre		'( (:) )'
79879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
79979115595Skre		'( ( true ))'
80079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
80179115595Skre		'( ( ( ( (  true )))))'
80279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
80379115595Skre		'( ( ( ( (true);:));true))'
80479115595Skre
80579115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
80679115595Skre		'()'
80779115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
80879115595Skre		'(   )'
80979115595Skre
81079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
81179115595Skre		'{ true; }'
81279115595Skre	atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
81379115595Skre		'{ false; }'
81479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
81579115595Skre		'{ { :; };}'
81679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
81779115595Skre		'{ { { { {  :;};};};};}'
81879115595Skre
81979115595Skre	atf_check -s exit:0 -o 'inline:}\n' -e empty ${TEST_SH} -c \
82079115595Skre		'{ echo } ; }'
82179115595Skre	atf_check -s exit:0 -o 'inline:{\n' -e empty ${TEST_SH} -c \
82279115595Skre		'{ echo { ; }'
82379115595Skre}
82479115595Skre
82579115595Skreatf_test_case q_for_loop
82679115595Skreq_for_loop_head() {
82779115595Skre	atf_set "descr" "Check for loop parsing"
82879115595Skre}
82979115595Skreq_for_loop_body() {
83079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
83179115595Skre		'for x; do : ; done'
83279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
83379115595Skre		'for x in ; do : ; done'
83479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
83579115595Skre		'for x in a b c ; do : ; done'
83679115595Skre
83779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
83879115595Skre		'for x in in;do : ; done'
83979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
84079115595Skre		'for x in for;do : ; done'
84179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
84279115595Skre		'for x in do;do : ; done'
84379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
84479115595Skre		'for for in in;do :;done'
84579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
84679115595Skre		'for for in for;do :; done'
84779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
84879115595Skre		'for for in do;do : ;done'
84979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
85079115595Skre		'for in in in;do : ; done'
85106627d31Skre	atf_check -s exit:0 -o 'inline:do\nin\ndo\n' -e empty ${TEST_SH} -c \
85206627d31Skre   'for in in in do in;do case $in in in)echo do;;do)echo in;;esac; done'
85379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
85479115595Skre		'for in in for;do : ; done'
85579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
85679115595Skre		'for in in do;do : ; done'
85779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
85879115595Skre		'for do in in;do : ; done'
85979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
86079115595Skre		'for do in for;do : ; done'
86179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
86279115595Skre		'for do in do;do : ; done'
86379115595Skre	atf_check -s exit:0 -o 'inline:dodo\n' -e empty ${TEST_SH} -c \
86479115595Skre		'for do in do;do echo ${do}do ; done'
86579115595Skre}
86679115595Skre
86779115595Skreatf_test_case r_case
86879115595Skrer_case_head() {
86979115595Skre	atf_set "descr" "Check case statement parsing"
87079115595Skre}
87179115595Skrer_case_body() {
87279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
87379115595Skre		'case x in  esac'
87479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
87579115595Skre		'case x in x) esac'
87679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
87779115595Skre		'case x in (x) esac'
87879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
87979115595Skre		'case x in x) ;; esac'
88079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
88179115595Skre		'case x in (x) ;; esac'
88279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
88379115595Skre		'case x in x|y) ;; esac'
88479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
88579115595Skre		'case x in (x|y) ;; esac'
88679115595Skre
88779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
88879115595Skre		'case x in x|esac) ;; esac'
88979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
89079115595Skre		'case x in x|esac|y) ;; esac'
89179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
89279115595Skre		'case x in (x|esac) ;; esac'
89379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
89479115595Skre		'case x in (x|esac|y) ;; esac'
89579115595Skre
89679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
89779115595Skre		'case x in in) esac'
89879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
89979115595Skre		'case x in in) ;; esac'
90079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
90179115595Skre		'case x in x|in) ;; esac'
90279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
90379115595Skre		'case x in x|in|y) ;; esac'
90479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
90579115595Skre		'case x in (x|in) ;; esac'
90679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
90779115595Skre		'case x in (in|x) ;; esac'
90879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
90979115595Skre		'case x in (x|in|y) ;; esac'
91079115595Skre
91179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
91279115595Skre		'case case in case) esac'
91379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
91479115595Skre		'case in in in) esac'
91579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
91679115595Skre		'case esac in (in) esac'
91779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
91879115595Skre		'case in in esac|cat'
91979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
92079115595Skre		'case esac in esac|cat'
92179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
92279115595Skre		'case in in esac|case x in u) echo foo;; esac'
92379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
92479115595Skre		'case esac in esac|case x in u) echo foo;; esac'
92579115595Skre	atf_check -s exit:0 -o 'inline:foo\n' -e empty ${TEST_SH} -c \
92679115595Skre		'case in in esac|case x in x) echo foo;; esac'
92779115595Skre
92879115595Skre	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
92979115595Skre		'case in in (esac|cat'
93079115595Skre
93179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
93279115595Skre		'case x in x );;esac'
93379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
93479115595Skre		'case x in ( x );;esac'
93579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
93679115595Skre		'case x in x | y );;esac'
93779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
93879115595Skre		'case x in ( x | y );;esac'
93979115595Skre
94079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
94179115595Skre		'case x
94279115595Skre		 in
94379115595Skre		 (    x    |    y    )
94479115595Skre
94579115595Skre			;;
94679115595Skre
94779115595Skre
94879115595Skre		esac
94979115595Skre		'
95079115595Skre}
95179115595Skre
95279115595Skreatf_test_case s_if
95379115595Skres_if_head() {
95479115595Skre	atf_set "descr" "Check if statement parsing"
95579115595Skre}
95679115595Skres_if_body() {
95779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
95879115595Skre		'if :; then :; fi'
95979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
96079115595Skre		'if :; then :; else :; fi'
96179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
96279115595Skre		'if :; then :; elif :; then :; else :; fi'
96379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
96479115595Skre		'if :; then :; elif :; then :; elif :; then :; else :; fi'
96579115595Skre
96679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
96779115595Skre		'if :; then : else :; fi'
96879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
96979115595Skre		'if : then :; then :; fi'
97079115595Skre
97179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
97279115595Skre		'if if :;then :;fi then :;fi'
97379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
97479115595Skre		'if if :;then if :;then :;fi fi;then :;fi'
97579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
97679115595Skre		'if if :;then :;fi;then :;else if :;then :;fi fi'
97779115595Skre
97879115595Skre	for a in true false; do
97979115595Skre		for b in true false; do
98079115595Skre			for c in true false; do
98179115595Skre
98279115595Skre				$a && out=a || {
98379115595Skre				$b && out=b || {
98479115595Skre				$c && out=c || {
98579115595Skre				out=d; };};}
98679115595Skre
98779115595Skre				atf_check -s exit:0 -e empty \
98879115595Skre					-o "inline:${out}"'\n' \
98979115595Skre					${TEST_SH} -c \
99079115595Skre						"if $a; then echo a
99179115595Skre						elif $b; then echo b
99279115595Skre						elif $c; then echo c
99379115595Skre						else echo d
99479115595Skre						fi"
99579115595Skre			done
99679115595Skre		done
99779115595Skre	done
99879115595Skre}
99979115595Skre
100079115595Skreatf_test_case t_loops
100179115595Skret_loops_head() {
100279115595Skre	atf_set "descr" "Check while/until loop parsing"
100379115595Skre}
100479115595Skret_loops_body() {
100579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
100679115595Skre		'while false; do :; done'
100779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
100879115595Skre		'while false; do \done; done'
100979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
101079115595Skre		'until :; do :; done'
101179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
101279115595Skre		'until :; do \done; done'
101379115595Skre
101479115595Skre	atf_check -s exit:0 -o 'inline:x\n1\n' -e empty ${TEST_SH} -c \
101579115595Skre		':; while (exit) do echo x; false; done; echo $?'
101679115595Skre	atf_check -s exit:0 -o 'inline:x\n0\n' -e empty ${TEST_SH} -c \
101779115595Skre		'false; until (exit) do echo x; done; echo $?'
101879115595Skre}
101979115595Skre
102079115595Skreatf_test_case u_case_cont
102179115595Skreu_case_cont_head() {
102279115595Skre	atf_set "descr" "Check case stmt parsing using ;& [optional]"
102379115595Skre}
102479115595Skreu_case_cont_body() {
102579115595Skre
102679115595Skre	${TEST_SH} -c 'case x in (x) false ;& (y) : ;; esac' 2>/dev/null ||
102779115595Skre		atf_skip ";& case list terminator unsupported in ${TEST_SH}"
102879115595Skre
102979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
103079115595Skre		'case x in x) ;& esac'
103179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
103279115595Skre		'case x in (x) ;& esac'
103379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
103479115595Skre		'case x in x|y) ;& esac'
103579115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
103679115595Skre		'case x in (x|y) ;& esac'
103779115595Skre
103879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
103979115595Skre		'case x in x );&esac'
104079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
104179115595Skre		'case x in ( x );&esac'
104279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
104379115595Skre		'case x in x | y );&esac'
104479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
104579115595Skre		'case x in ( x | y );&esac'
104679115595Skre
104779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
104879115595Skre		'case x in x) ;& (y) esac'
104979115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
105079115595Skre		'case x in (x) ;& esac'
105179115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
105279115595Skre		'case x in x|y) ;& esac'
105379115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
105479115595Skre		'case x in (x|y) ;& esac'
105579115595Skre}
105679115595Skre
105779115595Skreatf_test_case x_functions
105879115595Skrex_functions_head() {
105979115595Skre	atf_set "descr" "Check function definition parsing"
106079115595Skre}
106179115595Skrex_functions_body() {
106279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
106379115595Skre		'func() { :; }'
106479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
106579115595Skre		'func() { :; }; func'
106679115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
106779115595Skre		'func()(:)'
106879115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
106979115595Skre		'func()if :; then false; else true; fi'
107079115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
107179115595Skre		'func()while false; do :;done'
107279115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
107379115595Skre		'func () for a in b c; do :; done'
107479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
107579115595Skre		'func() case x in (y) esac'
107679115595Skre
107779115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
107879115595Skre		'f1() { f2() { :; }; }; f1; f2'
107979115595Skre
108079115595Skre	# f2 should be not found, but f1 clears $?
108179115595Skre	atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} -c \
108279115595Skre		'f1() { f2() { :; }; }; f2; f1'
108379115595Skre
108479115595Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
108579115595Skre		'f1() { eval "$1() { :; }"; }; f1 f2; f2'
108679115595Skre}
108779115595Skre
108821aab715Skreatf_test_case z_PR_48498
108921aab715Skrez_PR_48498_head() {
109021aab715Skre	atf_set "descr" "Check for detecting the syntax error from PR bin/48498"
109121aab715Skre}
109221aab715Skrez_PR_48498_body() {
109321aab715Skre
109421aab715Skre	# reserved words/operators that end things,
109521aab715Skre	# were completely ignored after a ';' or '&'
109621aab715Skre	# many of these tests lifted directly from the PR
109721aab715Skre
109821aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
109921aab715Skre		'true; fi'
110021aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
110121aab715Skre		'false; fi'
110221aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
110321aab715Skre		'false; then echo wut'
110421aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
110521aab715Skre		'true; then echo wut'
110621aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
110721aab715Skre		'true; do echo wut'
110821aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
110921aab715Skre		'true; then'
111021aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
111121aab715Skre		'true; else'
111221aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
111321aab715Skre		'true; do'
111421aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
111521aab715Skre		'true; done'
111621aab715Skre		# {
111721aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
111821aab715Skre		': ; }'
111921aab715Skre		# (
112021aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
112121aab715Skre		':;)'
112221aab715Skre
112321aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
112421aab715Skre		'true& fi'
112521aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
112621aab715Skre		'false& fi'
112721aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
112821aab715Skre		'false& then echo wut'
112921aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
113021aab715Skre		'true& then echo wut'
113121aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
113221aab715Skre		'true& do echo wut'
113321aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
113421aab715Skre		'true& then'
113521aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
113621aab715Skre		'true& else'
113721aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
113821aab715Skre		'true& do'
113921aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
114021aab715Skre		'true&done'
114121aab715Skre		# {
114221aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
114321aab715Skre		':&}'
114421aab715Skre		# (
114521aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
114621aab715Skre		':&)'
114721aab715Skre}
114821aab715Skre
114921aab715Skreatf_test_case z_PR_52426
115021aab715Skrez_PR_52426_head() {
115121aab715Skre	atf_set "descr" "Check for detecting the syntax error from PR bin/52426"
115221aab715Skre}
115321aab715Skrez_PR_52426_body() {
115421aab715Skre	# Absoluely anything was permitted as a pattern of a case
115521aab715Skre	# statement, any token (except 'esac') would serve
115621aab715Skre	# What follows are a few "pretty" examples that were accepted.
115721aab715Skre	# The first is the example from the PR
115821aab715Skre
115921aab715Skre	# Note we use only ;; type case lists, ;& should do the same, but
116021aab715Skre	# only for shells that support it, we do not want the shell to
116121aab715Skre	# object to any of these just because it does not support ;&
116221aab715Skre
116321aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
116421aab715Skre		'case x in <|() ;; esac'
116521aab715Skre
116621aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
116721aab715Skre		'case x in ((|)) ;; esac'
116821aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
116921aab715Skre		'case x in _|() ;; esac'
117021aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
117121aab715Skre		'case x in ()|() ;; esac'
117221aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
117321aab715Skre		'case x in -|;) ;; esac'
117421aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
117521aab715Skre		'case x in (;|-) ;; esac'
117621aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
117721aab715Skre		'case x in ;;|;) ;; esac'
117821aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
117921aab715Skre		'case x in (|| | ||) ;; esac'
118021aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
118121aab715Skre		'case x in (<<|>>) ;; esac'
118221aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
118321aab715Skre		'case x in (&&|&) ;; (|||>&) ;; &) esac'
118421aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
118521aab715Skre		'case x in (>||<) ;; esac'
118621aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
118721aab715Skre		'case x in( || | || | || | || | || );; esac'
118821aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
118921aab715Skre		'case x in (||| ||| ||| ||| ||) ;; esac'
119021aab715Skre	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
119121aab715Skre		'case x in <> |
119221aab715Skre		) ;; esac'
119321aab715Skre
119421aab715Skre	# now check some similar looking cases that are supposed to work
119521aab715Skre	# That is, make sure the fix for the PR does not break valid cases.
119621aab715Skre
119721aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
119821aab715Skre		'case fi in ({|}) ;; (!) ;; esac'
119921aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
120021aab715Skre		'case esac in ([|]);; (][);; !!!|!!!|!!!|!!!);; esac'
120121aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
120221aab715Skre		'case then in ({[]]}) ;; (^^);; (^|^);; ([!]);; (-);; esac'
120321aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
120421aab715Skre		'case while in while   );;(if|then|elif|fi);;(do|done);; esac'
120521aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
120621aab715Skre		'case until in($);;($$);;($4.50);;(1/2);;0.3333);;esac'
120721aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
120821aab715Skre		'case return in !);; !$);; $!);; !#);; (@);; esac'
120921aab715Skre	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
121021aab715Skre		'case break in (/);; (\/);; (/\|/\));; (\\//);; esac'
121121aab715Skre}
121221aab715Skre
12130b70db4eSkreatf_test_case z_PR_53712
12140b70db4eSkrez_PR_53712_head() {
12150b70db4eSkre	atf_set "descr" "Check for avoiding the core dump from PR bin/53712"
12160b70db4eSkre}
12170b70db4eSkrez_PR_53712_body() {
12180b70db4eSkre	atf_require_prog sysctl
12190b70db4eSkre	atf_require_prog rm
12200b70db4eSkre
12210b70db4eSkre	# Don't want to have to deal with all the possible ways
12220b70db4eSkre	# that the systcm might be configured to drop core files...
12230b70db4eSkre	sysctl -w proc.$$.corename=core ||
12240b70db4eSkre		atf_skip "Unable to set file name for core dump file"
12250b70db4eSkre	rm -f core
12260b70db4eSkre
12270b70db4eSkre	${TEST_SH} -c '{ } > out'; S=$?
12280b70db4eSkre	test -f core &&
12290b70db4eSkre		atf_fail "PR bin/53712: ${TEST_SH} dumps core: status=$S"
12300b70db4eSkre	test "$S" -lt 128 ||
12310b70db4eSkre		atf_fail "PR bin/53712: ${TEST_SH} reported status $S (core?)"
12320b70db4eSkre
12330b70db4eSkre	# It doesn't matter here whether or not there was an error
12340b70db4eSkre	# from the empty compound, or whether "out" was created
12350b70db4eSkre	# just that no core dump appeared, and the shell did not
12360b70db4eSkre	# exit because of a signal.
12370b70db4eSkre
12380b70db4eSkre	return 0
12390b70db4eSkre}
12400b70db4eSkre
124179115595Skreatf_init_test_cases() {
124279115595Skre	atf_add_test_case a_basic_tokenisation
124379115595Skre	atf_add_test_case b_comments
124479115595Skre	atf_add_test_case c_line_wrapping
1245327a7bf9Skre	atf_add_test_case d_cstrings
1246327a7bf9Skre	atf_add_test_case f_redirects
1247327a7bf9Skre	atf_add_test_case g_variable_syntax
1248327a7bf9Skre	atf_add_test_case h_var_assign
124979115595Skre	atf_add_test_case i_pipelines
125079115595Skre	atf_add_test_case j_and_or_lists
125179115595Skre	atf_add_test_case k_lists
125279115595Skre	atf_add_test_case l_async_lists
125379115595Skre	atf_add_test_case m_compound_lists
125479115595Skre	atf_add_test_case q_for_loop
125579115595Skre	atf_add_test_case r_case
125679115595Skre	atf_add_test_case s_if
125779115595Skre	atf_add_test_case t_loops
125879115595Skre	atf_add_test_case u_case_cont
125979115595Skre	atf_add_test_case x_functions
126021aab715Skre
126121aab715Skre	atf_add_test_case z_PR_48498
126221aab715Skre	atf_add_test_case z_PR_52426
12630b70db4eSkre	atf_add_test_case z_PR_53712
126479115595Skre}
1265