1303980Sngie# $NetBSD: t_cmdsub.sh,v 1.4 2016/04/04 12:40:13 christos Exp $
2303980Sngie#
3303980Sngie# Copyright (c) 2016 The NetBSD Foundation, Inc.
4303980Sngie# All rights reserved.
5303980Sngie#
6303980Sngie# Redistribution and use in source and binary forms, with or without
7303980Sngie# modification, are permitted provided that the following conditions
8303980Sngie# are met:
9303980Sngie# 1. Redistributions of source code must retain the above copyright
10303980Sngie#    notice, this list of conditions and the following disclaimer.
11303980Sngie# 2. Redistributions in binary form must reproduce the above copyright
12303980Sngie#    notice, this list of conditions and the following disclaimer in the
13303980Sngie#    documentation and/or other materials provided with the distribution.
14303980Sngie#
15303980Sngie# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16303980Sngie# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17303980Sngie# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18303980Sngie# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19303980Sngie# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20303980Sngie# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21303980Sngie# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22303980Sngie# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23303980Sngie# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24303980Sngie# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25303980Sngie# POSSIBILITY OF SUCH DAMAGE.
26303980Sngie#
27303980Sngie# the implementation of "sh" to test
28303980Sngie: ${TEST_SH:="/bin/sh"}
29303980Sngie
30303980Sngie#
31303980Sngie# This file tests command substitutions ( `...` and $( ... ) )
32303980Sngie#
33303980Sngie# CAUTION:
34303980Sngie#	Be careful attempting running these tests outside the ATF environment
35303980Sngie#	Some of the tests run "rm *" in the current directory to clean up
36303980Sngie#	An ATF test directory should be empty already, outside ATF, anything
37303980Sngie
38303980Sngieatf_test_case a_basic_cmdsub
39303980Sngiea_basic_cmdsub_head() {
40303980Sngie	atf_set "descr" 'Test operation of simple $( ) substitutions'
41303980Sngie}
42303980Sngiea_basic_cmdsub_body() {
43303980Sngie	atf_check -s exit:0 -o match:'Result is true today' -e empty \
44303980Sngie	    ${TEST_SH} -c \
45303980Sngie		'echo Result is $( true && echo true || echo false ) today'
46303980Sngie
47303980Sngie	atf_check -s exit:0 -o match:'Result is false today' -e empty \
48303980Sngie	    ${TEST_SH} -c \
49303980Sngie		'echo Result is $( false && echo true || echo false ) today'
50303980Sngie
51303980Sngie	atf_check -s exit:0 -o match:'aaabbbccc' -e empty \
52303980Sngie	    ${TEST_SH} -c 'echo aaa$( echo bbb )ccc'
53303980Sngie	atf_check -s exit:0 -o match:'aaabbb cccddd' -e empty \
54303980Sngie	    ${TEST_SH} -c 'echo aaa$( echo bbb ccc )ddd'
55303980Sngie	atf_check -s exit:0 -o inline:'aaabbb cccddd\n' -e empty \
56303980Sngie	    ${TEST_SH} -c 'echo aaa$( echo bbb; echo ccc )ddd'
57303980Sngie	atf_check -s exit:0 -o inline:'aaabbb\ncccddd\n' -e empty \
58303980Sngie	    ${TEST_SH} -c 'echo "aaa$( echo bbb; echo ccc )ddd"'
59303980Sngie
60303980Sngie	atf_check -s exit:0 -o inline:'some string\n' -e empty \
61303980Sngie	    ${TEST_SH} -c 'X=$( echo some string ); echo "$X"'
62303980Sngie	atf_check -s exit:0 -o inline:'weird; string *\n' -e empty \
63303980Sngie	    ${TEST_SH} -c 'X=$( echo "weird; string *" ); echo "$X"'
64303980Sngie
65303980Sngie	rm -f * 2>/dev/null || :
66303980Sngie	for f in file-1 file-2
67303980Sngie	do
68303980Sngie		cp /dev/null "$f"
69303980Sngie	done
70303980Sngie
71303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
72303980Sngie	    ${TEST_SH} -c 'echo Found $( echo * )'
73303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
74303980Sngie	    ${TEST_SH} -c 'echo Found "$( echo * )"'
75303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
76303980Sngie	    ${TEST_SH} -c 'echo Found $('" echo '*' )"
77303980Sngie	atf_check -s exit:0 -o match:'Found \*' -e empty \
78303980Sngie	    ${TEST_SH} -c 'echo Found "$('" echo '*' "')"'
79303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
80303980Sngie	    ${TEST_SH} -c 'echo Found $('" echo \\* )"
81303980Sngie	atf_check -s exit:0 -o match:'Found \*' -e empty \
82303980Sngie	    ${TEST_SH} -c 'echo Found "$('" echo \\* )"\"
83303980Sngie}
84303980Sngie
85303980Sngieatf_test_case b_basic_backticks
86303980Sngieb_basic_backticks_head() {
87303980Sngie	atf_set "descr" 'Test operation of old style ` ` substitutions'
88303980Sngie}
89303980Sngieb_basic_backticks_body() {
90303980Sngie	atf_check -s exit:0 -o match:'Result is true today' -e empty \
91303980Sngie	    ${TEST_SH} -c \
92303980Sngie		'echo Result is `true && echo true || echo false` today'
93303980Sngie
94303980Sngie	atf_check -s exit:0 -o match:'Result is false today' -e empty \
95303980Sngie	    ${TEST_SH} -c \
96303980Sngie		'echo Result is `false && echo true || echo false` today'
97303980Sngie
98303980Sngie	atf_check -s exit:0 -o match:'aaabbbccc' -e empty \
99303980Sngie	    ${TEST_SH} -c 'echo aaa` echo bbb `ccc'
100303980Sngie	atf_check -s exit:0 -o match:'aaabbb cccddd' -e empty \
101303980Sngie	    ${TEST_SH} -c 'echo aaa` echo bbb ccc `ddd'
102303980Sngie	atf_check -s exit:0 -o inline:'aaabbb cccddd\n' -e empty \
103303980Sngie	    ${TEST_SH} -c 'echo aaa` echo bbb; echo ccc `ddd'
104303980Sngie	atf_check -s exit:0 -o inline:'aaabbb\ncccddd\n' -e empty \
105303980Sngie	    ${TEST_SH} -c 'echo "aaa` echo bbb; echo ccc `ddd"'
106303980Sngie
107303980Sngie	atf_check -s exit:0 -o inline:'some string\n' -e empty \
108303980Sngie	    ${TEST_SH} -c 'X=` echo some string `; echo "$X"'
109303980Sngie	atf_check -s exit:0 -o inline:'weird; string *\n' -e empty \
110303980Sngie	    ${TEST_SH} -c 'X=` echo "weird; string *" `; echo "$X"'
111303980Sngie
112303980Sngie	rm -f * 2>/dev/null || :
113303980Sngie	for f in file-1 file-2
114303980Sngie	do
115303980Sngie		cp /dev/null "$f"
116303980Sngie	done
117303980Sngie
118303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
119303980Sngie	    ${TEST_SH} -c 'echo Found ` echo * `'
120303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
121303980Sngie	    ${TEST_SH} -c 'echo Found "` echo * `"'
122303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
123303980Sngie	    ${TEST_SH} -c 'echo Found `'" echo '*' "'`'
124303980Sngie	atf_check -s exit:0 -o match:'Found \*' -e empty \
125303980Sngie	    ${TEST_SH} -c 'echo Found "`'" echo '*' "'`"'
126303980Sngie	atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
127303980Sngie	    ${TEST_SH} -c 'echo Found `'" echo \\* "'`'
128303980Sngie	atf_check -s exit:0 -o match:'Found \*' -e empty \
129303980Sngie	    ${TEST_SH} -c 'echo Found "`'" echo \\* "'`"'
130303980Sngie}
131303980Sngie
132303980Sngieatf_test_case c_nested_cmdsub
133303980Sngiec_nested_cmdsub_head() {
134303980Sngie	atf_set "descr" "Test that cmd substitutions can be nested"
135303980Sngie}
136303980Sngiec_nested_cmdsub_body() {
137303980Sngie	atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
138303980Sngie	    ${TEST_SH} -c 'echo __$( echo foo$(echo bar)bletch )__'
139303980Sngie	atf_check -s exit:0 -o match:'_abcde_' -e empty \
140303980Sngie	    ${TEST_SH} -c 'echo _$(echo a$(echo $(echo b)c$(echo d))e )_'
141303980Sngie	atf_check -s exit:0 -o match:'123454321' -e empty \
142303980Sngie	    ${TEST_SH} -c 'echo 1$(echo 2$(echo 3$(echo 4$(echo 5)4)3)2)1'
143303980Sngie}
144303980Sngie
145303980Sngieatf_test_case d_nested_backticks
146303980Sngied_nested_backticks_head() {
147303980Sngie	atf_set "descr" "Tests that old style backtick cmd subs can be nested"
148303980Sngie}
149303980Sngied_nested_backticks_body() {
150303980Sngie	atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
151303980Sngie	    ${TEST_SH} -c 'echo __` echo foo\`echo bar\`bletch `__'
152303980Sngie	atf_check -s exit:0 -o match:'_abcde_' -e empty \
153303980Sngie	    ${TEST_SH} -c \
154303980Sngie		'echo _`echo a\`echo \\\`echo b\\\`c\\\`echo d\\\`\`e `_'
155303980Sngie	atf_check -s exit:0 -o match:'123454321' -e empty \
156303980Sngie	    ${TEST_SH} -c \
157303980Sngie	    'echo 1`echo 2\`echo 3\\\`echo 4\\\\\\\`echo 5\\\\\\\`4\\\`3\`2`1'
158303980Sngie}
159303980Sngie
160303980Sngieatf_test_case e_perverse_mixing
161303980Sngiee_perverse_mixing_head() {
162303980Sngie	atf_set "descr" \
163303980Sngie		"Checks various mixed new and old style cmd substitutions"
164303980Sngie}
165303980Sngiee_perverse_mixing_body() {
166303980Sngie	atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
167303980Sngie	    ${TEST_SH} -c 'echo __$( echo foo`echo bar`bletch )__'
168303980Sngie	atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
169303980Sngie	    ${TEST_SH} -c 'echo __` echo foo$(echo bar)bletch `__'
170303980Sngie	atf_check -s exit:0 -o match:'_abcde_' -e empty \
171303980Sngie	    ${TEST_SH} -c 'echo _$(echo a`echo $(echo b)c$(echo d)`e )_'
172303980Sngie	atf_check -s exit:0 -o match:'_abcde_' -e empty \
173303980Sngie	    ${TEST_SH} -c 'echo _`echo a$(echo \`echo b\`c\`echo d\`)e `_'
174303980Sngie	atf_check -s exit:0 -o match:'12345654321' -e empty \
175303980Sngie	    ${TEST_SH} -c \
176303980Sngie		'echo 1`echo 2$(echo 3\`echo 4\\\`echo 5$(echo 6)5\\\`4\`3)2`1'
177303980Sngie}
178303980Sngie
179303980Sngieatf_test_case f_redirect_in_cmdsub
180303980Sngief_redirect_in_cmdsub_head() {
181303980Sngie	atf_set "descr" "Checks that redirects work in command substitutions"
182303980Sngie}
183303980Sngief_redirect_in_cmdsub_body() {
184303980Sngie	atf_require_prog cat
185303980Sngie	atf_require_prog rm
186303980Sngie
187303980Sngie	rm -f file 2>/dev/null || :
188303980Sngie	atf_check -s exit:0 -o match:'_aa_' -e empty \
189303980Sngie	    ${TEST_SH} -c 'echo _$( echo a$( echo b > file )a)_'
190303980Sngie	atf_check -s exit:0 -o match:b -e empty ${TEST_SH} -c 'cat file'
191303980Sngie	atf_check -s exit:0 -o match:'_aba_' -e empty \
192303980Sngie	    ${TEST_SH} -c 'echo _$( echo a$( cat < file )a)_'
193303980Sngie	atf_check -s exit:0 -o match:'_aa_' -e empty \
194303980Sngie	    ${TEST_SH} -c 'echo _$( echo a$( echo d >> file )a)_'
195303980Sngie	atf_check -s exit:0 -o inline:'b\nd\n' -e empty ${TEST_SH} -c 'cat file'
196303980Sngie	atf_check -s exit:0 -o match:'_aa_' -e match:'not error' \
197303980Sngie	    ${TEST_SH} -c 'echo _$( echo a$( echo not error >&2 )a)_'
198303980Sngie}
199303980Sngie
200303980Sngieatf_test_case g_redirect_in_backticks
201303980Sngieg_redirect_in_backticks_head() {
202303980Sngie	atf_set "descr" "Checks that redirects work in old style cmd sub"
203303980Sngie}
204303980Sngieg_redirect_in_backticks_body() {
205303980Sngie	atf_require_prog cat
206303980Sngie	atf_require_prog rm
207303980Sngie
208303980Sngie	rm -f file 2>/dev/null || :
209303980Sngie	atf_check -s exit:0 -o match:'_aa_' -e empty \
210303980Sngie	    ${TEST_SH} -c 'echo _` echo a\` echo b > file \`a`_'
211303980Sngie	atf_check -s exit:0 -o match:b -e empty ${TEST_SH} -c 'cat file'
212303980Sngie	atf_check -s exit:0 -o match:'_aba_' -e empty \
213303980Sngie	    ${TEST_SH} -c 'echo _` echo a\` cat < file \`a`_'
214303980Sngie	atf_check -s exit:0 -o match:'_aa_' -e empty \
215303980Sngie	    ${TEST_SH} -c 'echo _` echo a\` echo d >> file \`a`_'
216303980Sngie	atf_check -s exit:0 -o inline:'b\nd\n' -e empty ${TEST_SH} -c 'cat file'
217303980Sngie	atf_check -s exit:0 -o match:'_aa_' -e match:'not error' \
218303980Sngie	    ${TEST_SH} -c 'echo _` echo a\` echo not error >&2 \`a`_'
219303980Sngie}
220303980Sngie
221303980Sngieatf_test_case h_vars_in_cmdsub
222303980Sngieh_vars_in_cmdsub_head() {
223303980Sngie	atf_set "descr" "Check that variables work in command substitutions"
224303980Sngie}
225303980Sngieh_vars_in_cmdsub_body() {
226303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
227303980Sngie	    ${TEST_SH} -c 'X=abc; echo __$( echo ${X} )__'
228303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
229303980Sngie	    ${TEST_SH} -c 'X=abc; echo __$( echo "${X}" )__'
230303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
231303980Sngie	    ${TEST_SH} -c 'X=abc; echo "__$( echo ${X} )__"'
232303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
233303980Sngie	    ${TEST_SH} -c 'X=abc; echo "__$( echo "${X}" )__"'
234303980Sngie
235303980Sngie	atf_check -s exit:0 -o inline:'a\n\nb\n\nc\n' -e empty \
236303980Sngie	    ${TEST_SH} -c "for X in a '' b '' c"'; do echo $( echo "$X" ); done'
237303980Sngie
238303980Sngie	atf_check -s exit:0 -o match:'__acd__' -e empty \
239303980Sngie	    ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X-b}${Y-c}d)__"'
240303980Sngie	atf_check -s exit:0 -o match:'__abcd__' -e empty \
241303980Sngie	    ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X:-b}${Y:-c}d)__"'
242303980Sngie	atf_check -s exit:0 -o match:'__XYX__' -e empty \
243303980Sngie	    ${TEST_SH} -c 'X=X; echo "__${X}$( X=Y; echo ${X} )${X}__"'
244303980Sngie	atf_check -s exit:0 -o match:'__def__' -e empty \
245303980Sngie	    ${TEST_SH} -c 'X=abc; echo "__$(X=def; echo "${X}" )__"'
246303980Sngie	atf_check -s exit:0 -o inline:'abcdef\nabc\n' -e empty \
247303980Sngie	    ${TEST_SH} -c 'X=abc; echo "$X$(X=def; echo ${X} )"; echo $X'
248303980Sngie}
249303980Sngie
250303980Sngieatf_test_case i_vars_in_backticks
251303980Sngiei_vars_in_backticks_head() {
252303980Sngie	atf_set "descr" "Checks that variables work in old style cmd sub"
253303980Sngie}
254303980Sngiei_vars_in_backticks_body() {
255303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
256303980Sngie	    ${TEST_SH} -c 'X=abc; echo __` echo ${X} `__'
257303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
258303980Sngie	    ${TEST_SH} -c 'X=abc; echo __` echo "${X}" `__'
259303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
260303980Sngie	    ${TEST_SH} -c 'X=abc; echo "__` echo ${X} `__"'
261303980Sngie	atf_check -s exit:0 -o match:'__abc__' -e empty \
262303980Sngie	    ${TEST_SH} -c 'X=abc; echo "__` echo \"${X}\" `__"'
263303980Sngie
264303980Sngie	atf_check -s exit:0 -o inline:'a\n\nb\n\nc\n' -e empty \
265303980Sngie	    ${TEST_SH} -c "for X in a '' b '' c"'; do echo $( echo "$X" ); done'
266303980Sngie
267303980Sngie	atf_check -s exit:0 -o match:'__acd__' -e empty \
268303980Sngie	    ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X-b}${Y-c}d)__"'
269303980Sngie	atf_check -s exit:0 -o match:'__abcd__' -e empty \
270303980Sngie	    ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X:-b}${Y:-c}d)__"'
271303980Sngie	atf_check -s exit:0 -o match:'__XYX__' -e empty \
272303980Sngie	    ${TEST_SH} -c 'X=X; echo "__${X}$( X=Y; echo ${X} )${X}__"'
273303980Sngie	atf_check -s exit:0 -o inline:'abcdef\nabc\n' -e empty \
274303980Sngie	    ${TEST_SH} -c 'X=abc; echo "$X`X=def; echo \"${X}\" `";echo $X'
275303980Sngie
276303980Sngie	# The following is nonsense, so is not included ...
277303980Sngie	# atf_check -s exit:0 -o match:'__abc__' -e empty \
278303980Sngie	#                              oV             cV   oV   cV
279303980Sngie	#    ${TEST_SH} -c 'X=abc; echo "__`X=def echo "${X}" `__"'
280303980Sngie	#				   `start in " ^ " ends, ` not yet
281303980Sngie}
282303980Sngie
283303980Sngieatf_test_case j_cmdsub_in_varexpand
284303980Sngiej_cmdsub_in_varexpand_head() {
285303980Sngie	atf_set "descr" "Checks that command sub can be used in var expansion"
286303980Sngie}
287303980Sngiej_cmdsub_in_varexpand_body() {
288303980Sngie	atf_check -s exit:0 -o match:'foo' -e empty \
289303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X+$(echo foo)}'
290303980Sngie	atf_check -s exit:0 -o match:'set' -e empty \
291303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X-$(echo foo)}'
292303980Sngie	rm -f bar 2>/dev/null || :
293303980Sngie	atf_check -s exit:0 -o match:'set' -e empty \
294303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X-$(echo foo > bar)}'
295303980Sngie	test -f bar && atf_fail "bar should not exist, but does"
296303980Sngie	atf_check -s exit:0 -o inline:'\n' -e empty \
297303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X+$(echo foo > bar)}'
298303980Sngie	test -f bar || atf_fail "bar should exist, but does not"
299303980Sngie}
300303980Sngie
301303980Sngieatf_test_case k_backticks_in_varexpand
302303980Sngiek_backticks_in_varexpand_head() {
303303980Sngie	atf_set "descr" "Checks that old style cmd sub works in var expansion"
304303980Sngie}
305303980Sngiek_backticks_in_varexpand_body() {
306303980Sngie	atf_check -s exit:0 -o match:'foo' -e empty \
307303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X+`echo foo`}'
308303980Sngie	atf_check -s exit:0 -o match:'set' -e empty \
309303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X-`echo foo`}'
310303980Sngie	rm -f bar 2>/dev/null || :
311303980Sngie	atf_check -s exit:0 -o match:'set' -e empty \
312303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X-`echo foo > bar`}'
313303980Sngie	test -f bar && atf_fail "bar should not exist, but does"
314303980Sngie	atf_check -s exit:0 -o inline:'\n' -e empty \
315303980Sngie	    ${TEST_SH} -c 'X=set; echo ${X+`echo foo > bar`}'
316303980Sngie	test -f bar || atf_fail "bar should exist, but does not"
317303980Sngie}
318303980Sngie
319303980Sngieatf_test_case l_arithmetic_in_cmdsub
320303980Sngiel_arithmetic_in_cmdsub_head() {
321303980Sngie	atf_set "descr" "Checks that arithmetic works in cmd substitutions"
322303980Sngie}
323303980Sngiel_arithmetic_in_cmdsub_body() {
324303980Sngie	atf_check -s exit:0 -o inline:'1 + 1 = 2\n' -e empty \
325303980Sngie	    ${TEST_SH} -c 'echo 1 + 1 = $( echo $(( 1 + 1 )) )'
326303980Sngie	atf_check -s exit:0 -o inline:'X * Y = 6\n' -e empty \
327303980Sngie	    ${TEST_SH} -c 'X=2; Y=3; echo X \* Y = $( echo $(( X * Y )) )'
328303980Sngie	atf_check -s exit:0 -o inline:'Y % X = 1\n' -e empty \
329303980Sngie	    ${TEST_SH} -c 'X=2; Y=3; echo Y % X = $( echo $(( $Y % $X )) )'
330303980Sngie}
331303980Sngie
332303980Sngieatf_test_case m_arithmetic_in_backticks
333303980Sngiem_arithmetic_in_backticks_head() {
334303980Sngie	atf_set "descr" "Checks that arithmetic works in old style cmd sub"
335303980Sngie}
336303980Sngiem_arithmetic_in_backticks_body() {
337303980Sngie	atf_check -s exit:0 -o inline:'2 + 3 = 5\n' -e empty \
338303980Sngie	    ${TEST_SH} -c 'echo 2 + 3 = ` echo $(( 2 + 3 )) `'
339303980Sngie	atf_check -s exit:0 -o inline:'X * Y = 6\n' -e empty \
340303980Sngie	    ${TEST_SH} -c 'X=2; Y=3; echo X \* Y = ` echo $(( X * Y )) `'
341303980Sngie	atf_check -s exit:0 -o inline:'Y % X = 1\n' -e empty \
342303980Sngie	    ${TEST_SH} -c 'X=2; Y=3; echo Y % X = ` echo $(( $Y % $X )) `'
343303980Sngie}
344303980Sngie
345303980Sngieatf_test_case n_cmdsub_in_arithmetic
346303980Sngien_cmdsub_in_arithmetic_head() {
347303980Sngie	atf_set "descr" "Tests uses of command substitutions in arithmetic"
348303980Sngie}
349303980Sngien_cmdsub_in_arithmetic_body() {
350303980Sngie	atf_check -s exit:0 -o inline:'7\n' -e empty \
351303980Sngie	    ${TEST_SH} -c 'echo $(( $( echo 3 ) $( echo + ) $( echo 4 ) ))'
352303980Sngie	atf_check -s exit:0 -o inline:'11\n7\n18\n4\n1\n' -e empty \
353303980Sngie	    ${TEST_SH} -c \
354303980Sngie		 'for op in + - \* / %
355303980Sngie		  do
356303980Sngie		      echo $(( $( echo 9 ) $( echo "${op}" ) $( echo 2 ) ))
357303980Sngie		  done'
358303980Sngie}
359303980Sngie
360303980Sngieatf_test_case o_backticks_in_arithmetic
361303980Sngieo_backticks_in_arithmetic_head() {
362303980Sngie	atf_set "descr" "Tests old style cmd sub used in arithmetic"
363303980Sngie}
364303980Sngieo_backticks_in_arithmetic_body() {
365303980Sngie	atf_check -s exit:0 -o inline:'33\n' -e empty \
366303980Sngie	    ${TEST_SH} -c 'echo $(( `echo 77` `echo -` `echo 44`))'
367303980Sngie	atf_check -s exit:0 -o inline:'14\n8\n33\n3\n2\n' -e empty \
368303980Sngie	    ${TEST_SH} -c \
369303980Sngie		 'for op in + - \* / %
370303980Sngie		  do
371303980Sngie		      echo $((`echo 11``echo "${op}"``echo 3`))
372303980Sngie		  done'
373303980Sngie}
374303980Sngie
375303980Sngieatf_test_case p_cmdsub_in_heredoc
376303980Sngiep_cmdsub_in_heredoc_head() {
377303980Sngie	atf_set "descr" "Checks that cmdsubs work inside a here document"
378303980Sngie}
379303980Sngiep_cmdsub_in_heredoc_body() {
380303980Sngie	atf_require_prog cat
381303980Sngie
382303980Sngie	atf_check -s exit:0 -o inline:'line 1+1\nline 2\nline 3\n' -e empty \
383303980Sngie	    ${TEST_SH} -c \
384303980Sngie		'cat <<- EOF
385303980Sngie			$( echo line 1 )$( echo +1 )
386303980Sngie			$( echo line 2;echo line 3 )
387303980Sngie		EOF'
388303980Sngie}
389303980Sngie
390303980Sngieatf_test_case q_backticks_in_heredoc
391303980Sngieq_backticks_in_heredoc_head() {
392303980Sngie	atf_set "descr" "Checks that old style cmdsubs work in here docs"
393303980Sngie}
394303980Sngieq_backticks_in_heredoc_body() {
395303980Sngie	atf_require_prog cat
396303980Sngie
397303980Sngie	atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
398303980Sngie	    ${TEST_SH} -c \
399303980Sngie		'cat <<- EOF
400303980Sngie			`echo Mary ` `echo had a `
401303980Sngie			` echo little; echo lamb `
402303980Sngie		EOF'
403303980Sngie}
404303980Sngie
405303980Sngieatf_test_case r_heredoc_in_cmdsub
406303980Sngier_heredoc_in_cmdsub_head() {
407303980Sngie	atf_set "descr" "Checks that here docs work inside cmd subs"
408303980Sngie}
409303980Sngier_heredoc_in_cmdsub_body() {
410303980Sngie	atf_require_prog cat
411303980Sngie
412303980Sngie	atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
413303980Sngie	    ${TEST_SH} -c 'echo "$( cat <<- \EOF
414303980Sngie				Mary had a
415303980Sngie				little
416303980Sngie				lamb
417303980Sngie			EOF
418303980Sngie			)"'
419303980Sngie
420303980Sngie	atf_check -s exit:0 -e empty \
421303980Sngie	    -o inline:'Mary had 1\nlittle\nlamb\nMary had 4\nlittle\nlambs\n' \
422303980Sngie	    ${TEST_SH} -c 'for N in 1 4; do echo "$( cat <<- EOF
423303980Sngie				Mary had ${N}
424303980Sngie				little
425303980Sngie				lamb$( [ $N -gt 1 ] && echo s )
426303980Sngie			EOF
427303980Sngie			)"; done'
428303980Sngie
429303980Sngie
430303980Sngie	atf_check -s exit:0 -o inline:'A Calculation:\n2 * 7 = 14\n' -e empty \
431303980Sngie	    ${TEST_SH} -c 'echo "$( cat <<- EOF
432303980Sngie				A Calculation:
433303980Sngie					2 * 7 = $(( 2 * 7 ))
434303980Sngie			EOF
435303980Sngie			)"'
436303980Sngie}
437303980Sngie
438303980Sngieatf_test_case s_heredoc_in_backticks
439303980Sngies_heredoc_in_backticks_head() {
440303980Sngie	atf_set "descr" "Checks that here docs work inside old style cmd subs"
441303980Sngie}
442303980Sngies_heredoc_in_backticks_body() {
443303980Sngie	atf_require_prog cat
444303980Sngie
445303980Sngie	atf_check -s exit:0 -o inline:'Mary had a little lamb\n' -e empty \
446303980Sngie	    ${TEST_SH} -c 'echo ` cat <<- \EOF
447303980Sngie				Mary had a
448303980Sngie				little
449303980Sngie				lamb
450303980Sngie			EOF
451303980Sngie			`'
452303980Sngie
453303980Sngie	atf_check -s exit:0 -o inline:'A Calculation:\n17 / 3 = 5\n' -e empty \
454303980Sngie	    ${TEST_SH} -c 'echo "` cat <<- EOF
455303980Sngie				A Calculation:
456303980Sngie					17 / 3 = $(( 17 / 3 ))
457303980Sngie			EOF
458303980Sngie			`"'
459303980Sngie}
460303980Sngie
461303980Sngieatf_test_case t_nested_cmdsubs_in_heredoc
462303980Sngiet_nested_cmdsubs_in_heredoc_head() {
463303980Sngie	atf_set "descr" "Checks nested command substitutions in here docs"
464303980Sngie}
465303980Sngiet_nested_cmdsubs_in_heredoc_body() {
466303980Sngie	atf_require_prog cat
467303980Sngie	atf_require_prog rm
468303980Sngie
469303980Sngie	rm -f * 2>/dev/null || :
470303980Sngie	echo "Hello" > File
471303980Sngie
472303980Sngie	atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
473303980Sngie	    ${TEST_SH} -c 'cat <<- EOF
474303980Sngie		$(cat File) U
475303980Sngie		$( V=$(cat File); echo "${V%lo}p" ) me!
476303980Sngie		EOF'
477303980Sngie
478303980Sngie	rm -f * 2>/dev/null || :
479303980Sngie	echo V>V ; echo A>A; echo R>R
480303980Sngie	echo Value>VAR
481303980Sngie
482303980Sngie	atf_check -s exit:0 -o inline:'$2.50\n' -e empty \
483303980Sngie	    ${TEST_SH} -c 'cat <<- EOF
484303980Sngie	$(Value='\''$2.50'\'';eval echo $(eval $(cat V)$(cat A)$(cat R)=\'\''\$$(cat $(cat V)$(cat A)$(cat R))\'\''; eval echo \$$(set -- *;echo ${3}${1}${2})))
485303980Sngie		EOF'
486303980Sngie}
487303980Sngie
488303980Sngieatf_test_case u_nested_backticks_in_heredoc
489303980Sngieu_nested_backticks_in_heredoc_head() {
490303980Sngie	atf_set "descr" "Checks nested old style cmd subs in here docs"
491303980Sngie}
492303980Sngieu_nested_backticks_in_heredoc_body() {
493303980Sngie	atf_require_prog cat
494303980Sngie	atf_require_prog rm
495303980Sngie
496303980Sngie	rm -f * 2>/dev/null || :
497303980Sngie	echo "Hello" > File
498303980Sngie
499303980Sngie	atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
500303980Sngie	    ${TEST_SH} -c 'cat <<- EOF
501303980Sngie		`cat File` U
502303980Sngie		`V=\`cat File\`; echo "${V%lo}p" ` me!
503303980Sngie		EOF'
504303980Sngie
505303980Sngie	rm -f * 2>/dev/null || :
506303980Sngie	echo V>V ; echo A>A; echo R>R
507303980Sngie	echo Value>VAR
508303980Sngie
509303980Sngie	atf_check -s exit:0 -o inline:'$5.20\n' -e empty \
510303980Sngie	    ${TEST_SH} -c 'cat <<- EOF
511303980Sngie	`Value='\''$5.20'\'';eval echo \`eval \\\`cat V\\\`\\\`cat A\\\`\\\`cat R\\\`=\\\'\''\\\$\\\`cat \\\\\\\`cat V\\\\\\\`\\\\\\\`cat A\\\\\\\`\\\\\\\`cat R\\\\\\\`\\\`\\\'\''; eval echo \\\$\\\`set -- *;echo \\\\\${3}\\\\\${1}\\\\\${2}\\\`\``
512303980Sngie		EOF'
513303980Sngie}
514303980Sngie
515303980Sngieatf_test_case v_cmdsub_paren_tests
516303980Sngiev_cmdsub__paren_tests_head() {
517303980Sngie	atf_set "descr" "tests with cmdsubs containing embedded ')'"
518303980Sngie}
519303980Sngiev_cmdsub_paren_tests_body() {
520303980Sngie
521303980Sngie	# Tests from:
522303980Sngie	#	http://www.in-ulm.de/~mascheck/various/cmd-subst/
523303980Sngie	# (slightly modified.)
524303980Sngie
525303980Sngie	atf_check -s exit:0 -o inline:'A.1\n' -e empty ${TEST_SH} -c \
526303980Sngie		'echo $(
527303980Sngie			case x in  x) echo A.1;; esac
528303980Sngie		)'
529303980Sngie
530303980Sngie	atf_check -s exit:0 -o inline:'A.2\n' -e empty ${TEST_SH} -c \
531303980Sngie		'echo $(
532303980Sngie			case x in  x) echo A.2;; esac # comment
533303980Sngie		)'
534303980Sngie
535303980Sngie	atf_check -s exit:0 -o inline:'A.3\n' -e empty ${TEST_SH} -c \
536303980Sngie		'echo $(
537303980Sngie			case x in (x) echo A.3;; esac
538303980Sngie		)'
539303980Sngie
540303980Sngie	atf_check -s exit:0 -o inline:'A.4\n' -e empty ${TEST_SH} -c \
541303980Sngie		'echo $(
542303980Sngie			case x in (x) echo A.4;; esac # comment
543303980Sngie		)'
544303980Sngie
545303980Sngie	atf_check -s exit:0 -o inline:'A.5\n' -e empty ${TEST_SH} -c \
546303980Sngie		'echo $(
547303980Sngie			case x in (x) echo A.5
548303980Sngie			esac
549303980Sngie		)'
550303980Sngie
551303980Sngie	atf_check -s exit:0 -o inline:'B: quoted )\n' -e empty ${TEST_SH} -c \
552303980Sngie		'echo $(
553303980Sngie			echo '\''B: quoted )'\''
554303980Sngie		)'
555303980Sngie
556303980Sngie	atf_check -s exit:0 -o inline:'C: comment then closing paren\n' \
557303980Sngie		-e empty ${TEST_SH} -c \
558303980Sngie			'echo $(
559303980Sngie				echo C: comment then closing paren # )
560303980Sngie			)'
561303980Sngie
562303980Sngie	atf_check -s exit:0 -o inline:'D.1: here-doc with )\n' \
563303980Sngie		-e empty ${TEST_SH} -c \
564303980Sngie			'echo $(
565303980Sngie				cat <<-\eof
566303980Sngie				D.1: here-doc with )
567303980Sngie				eof
568303980Sngie			)'
569303980Sngie
570303980Sngie	# D.2 is a bogus test.
571303980Sngie
572303980Sngie	atf_check -s exit:0 -o inline:'D.3: here-doc with \()\n' \
573303980Sngie		-e empty ${TEST_SH} -c \
574303980Sngie			'echo $(
575303980Sngie				cat <<-\eof
576303980Sngie				D.3: here-doc with \()
577303980Sngie				eof
578303980Sngie			)'
579303980Sngie
580303980Sngie	atf_check -s exit:0 -e empty \
581303980Sngie	  -o inline:'E: here-doc terminated with a parenthesis ("academic")\n' \
582303980Sngie		${TEST_SH} -c \
583303980Sngie		'echo $(
584303980Sngie			cat <<-\)
585303980Sngie			E: here-doc terminated with a parenthesis ("academic")
586303980Sngie			)
587303980Sngie		)'
588303980Sngie
589303980Sngie	atf_check -s exit:0 -e empty \
590303980Sngie-o inline:'F.1: here-doc embed with unbal single, back- or doublequote '\''\n' \
591303980Sngie		${TEST_SH} -c \
592303980Sngie		'echo $(
593303980Sngie			cat <<-"eof"
594303980Sngie		F.1: here-doc embed with unbal single, back- or doublequote '\''
595303980Sngie			eof
596303980Sngie		)'
597303980Sngie	atf_check -s exit:0 -e empty \
598303980Sngie -o inline:'F.2: here-doc embed with unbal single, back- or doublequote "\n' \
599303980Sngie		${TEST_SH} -c \
600303980Sngie		'echo $(
601303980Sngie			cat <<-"eof"
602303980Sngie		F.2: here-doc embed with unbal single, back- or doublequote "
603303980Sngie			eof
604303980Sngie		)'
605303980Sngie	atf_check -s exit:0 -e empty \
606303980Sngie -o inline:'F.3: here-doc embed with unbal single, back- or doublequote `\n' \
607303980Sngie		${TEST_SH} -c \
608303980Sngie		'echo $(
609303980Sngie			cat <<-"eof"
610303980Sngie		F.3: here-doc embed with unbal single, back- or doublequote `
611303980Sngie			eof
612303980Sngie		)'
613303980Sngie
614303980Sngie	atf_check -s exit:0 -e empty -o inline:'G: backslash at end of line\n' \
615303980Sngie		${TEST_SH} -c \
616303980Sngie			'echo $(
617303980Sngie				echo G: backslash at end of line # \
618303980Sngie			)'
619303980Sngie
620303980Sngie	atf_check -s exit:0 -e empty \
621303980Sngie		-o inline:'H: empty command-substitution\n' \
622303980Sngie		${TEST_SH} -c 'echo H: empty command-substitution $( )'
623303980Sngie}
624303980Sngie
625303980Sngieatf_test_case w_heredoc_outside_cmdsub
626303980Sngiew_heredoc_outside_cmdsub_head() {
627303980Sngie	atf_set "descr" "Checks that here docs work inside cmd subs"
628303980Sngie}
629303980Sngiew_heredoc_outside_cmdsub_body() {
630303980Sngie	atf_require_prog cat
631303980Sngie
632303980Sngie	atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
633303980Sngie	    ${TEST_SH} -c 'echo "$( cat <<- \EOF )"
634303980Sngie				Mary had a
635303980Sngie				little
636303980Sngie				lamb
637303980Sngie			EOF
638303980Sngie			'
639303980Sngie
640303980Sngie	atf_check -s exit:0 -e empty \
641303980Sngie	    -o inline:'Mary had 1\nlittle\nlamb\nMary had 4\nlittle\nlambs\n' \
642303980Sngie	    ${TEST_SH} -c 'for N in 1 4; do echo "$( cat <<- EOF )"
643303980Sngie				Mary had ${N}
644303980Sngie				little
645303980Sngie				lamb$( [ $N -gt 1 ] && echo s )
646303980Sngie			EOF
647303980Sngie			done'
648303980Sngie
649303980Sngie
650303980Sngie	atf_check -s exit:0 -o inline:'A Calculation:\n2 * 7 = 14\n' -e empty \
651303980Sngie	    ${TEST_SH} -c 'echo "$( cat <<- EOF)"
652303980Sngie				A Calculation:
653303980Sngie					2 * 7 = $(( 2 * 7 ))
654303980Sngie			EOF
655303980Sngie			'
656303980Sngie}
657303980Sngie
658303980Sngieatf_test_case x_heredoc_outside_backticks
659303980Sngiex_heredoc_outside_backticks_head() {
660303980Sngie	atf_set "descr" "Checks that here docs work inside old style cmd subs"
661303980Sngie}
662303980Sngiex_heredoc_outside_backticks_body() {
663303980Sngie	atf_require_prog cat
664303980Sngie
665303980Sngie	atf_check -s exit:0 -o inline:'Mary had a little lamb\n' -e empty \
666303980Sngie	    ${TEST_SH} -c 'echo ` cat <<- \EOF `
667303980Sngie				Mary had a
668303980Sngie				little
669303980Sngie				lamb
670303980Sngie			EOF
671303980Sngie			'
672303980Sngie
673303980Sngie	atf_check -s exit:0 -o inline:'A Calculation:\n17 / 3 = 5\n' -e empty \
674303980Sngie	    ${TEST_SH} -c 'echo "` cat <<- EOF `"
675303980Sngie				A Calculation:
676303980Sngie					17 / 3 = $(( 17 / 3 ))
677303980Sngie			EOF
678303980Sngie			'
679303980Sngie}
680303980Sngie
681303980Sngieatf_test_case t_nested_cmdsubs_in_heredoc
682303980Sngiet_nested_cmdsubs_in_heredoc_head() {
683303980Sngie	atf_set "descr" "Checks nested command substitutions in here docs"
684303980Sngie}
685303980Sngiet_nested_cmdsubs_in_heredoc_body() {
686303980Sngie	atf_require_prog cat
687303980Sngie	atf_require_prog rm
688303980Sngie
689303980Sngie	rm -f * 2>/dev/null || :
690303980Sngie	echo "Hello" > File
691303980Sngie
692303980Sngie	atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
693303980Sngie	    ${TEST_SH} -c 'cat <<- EOF
694303980Sngie		$(cat File) U
695303980Sngie		$( V=$(cat File); echo "${V%lo}p" ) me!
696303980Sngie		EOF'
697303980Sngie
698303980Sngie	rm -f * 2>/dev/null || :
699303980Sngie	echo V>V ; echo A>A; echo R>R
700303980Sngie	echo Value>VAR
701303980Sngie
702303980Sngie	atf_check -s exit:0 -o inline:'$2.50\n' -e empty \
703303980Sngie	    ${TEST_SH} -c 'cat <<- EOF
704303980Sngie	$(Value='\''$2.50'\'';eval echo $(eval $(cat V)$(cat A)$(cat R)=\'\''\$$(cat $(cat V)$(cat A)$(cat R))\'\''; eval echo \$$(set -- *;echo ${3}${1}${2})))
705303980Sngie		EOF'
706303980Sngie}
707303980Sngie
708303980Sngieatf_test_case z_absurd_heredoc_cmdsub_combos
709303980Sngiez_absurd_heredoc_cmdsub_combos_head() {
710303980Sngie	atf_set "descr" "perverse and unusual cmd substitutions & more"
711303980Sngie}
712303980Sngiez_absurd_heredoc_cmdsub_combos_body() {
713303980Sngie
714303980Sngie	echo "Help!" > help
715303980Sngie
716303980Sngie	# This version works in NetBSD (& FreeBSD)'s sh (and most others)
717303980Sngie	atf_check -s exit:0 -o inline:'Help!\nMe 2\n' -e empty ${TEST_SH} -c '
718303980Sngie			cat <<- EOF
719303980Sngie				$(
720303980Sngie					cat <<- STOP
721303980Sngie						$(
722303980Sngie							cat `echo help`
723303980Sngie						)
724303980Sngie					STOP
725303980Sngie				)
726303980Sngie				$(
727303980Sngie					cat <<- END 4<<-TRASH
728303980Sngie						Me $(( 1 + 1 ))
729303980Sngie					END
730303980Sngie					This is unused noise!
731303980Sngie					TRASH
732303980Sngie				)
733303980Sngie			EOF
734303980Sngie		'
735303980Sngie
736303980Sngie	# atf_expect_fail "PR bin/50993 - heredoc parsing done incorrectly"
737303980Sngie	atf_check -s exit:0 -o inline:'Help!\nMe 2\n' -e empty ${TEST_SH} -c '
738303980Sngie			cat <<- EOF
739303980Sngie				$(
740303980Sngie					cat << STOP
741303980Sngie						$(
742303980Sngie							cat `echo help`
743303980Sngie						)
744303980Sngie					STOP
745303980Sngie				)
746303980Sngie				$(
747303980Sngie					cat <<- END 4<<TRASH
748303980Sngie						Me $(( 1 + 1 ))
749303980Sngie					END
750303980Sngie					This is unused noise!
751303980Sngie					TRASH
752303980Sngie				)
753303980Sngie			EOF
754303980Sngie		'
755303980Sngie}
756303980Sngie
757303980Sngieatf_init_test_cases() {
758303980Sngie	atf_add_test_case a_basic_cmdsub
759303980Sngie	atf_add_test_case b_basic_backticks
760303980Sngie	atf_add_test_case c_nested_cmdsub
761303980Sngie	atf_add_test_case d_nested_backticks
762303980Sngie	atf_add_test_case e_perverse_mixing
763303980Sngie	atf_add_test_case f_redirect_in_cmdsub
764303980Sngie	atf_add_test_case g_redirect_in_backticks
765303980Sngie	atf_add_test_case h_vars_in_cmdsub
766303980Sngie	atf_add_test_case i_vars_in_backticks
767303980Sngie	atf_add_test_case j_cmdsub_in_varexpand
768303980Sngie	atf_add_test_case k_backticks_in_varexpand
769303980Sngie	atf_add_test_case l_arithmetic_in_cmdsub
770303980Sngie	atf_add_test_case m_arithmetic_in_backticks
771303980Sngie	atf_add_test_case n_cmdsub_in_arithmetic
772303980Sngie	atf_add_test_case o_backticks_in_arithmetic
773303980Sngie	atf_add_test_case p_cmdsub_in_heredoc
774303980Sngie	atf_add_test_case q_backticks_in_heredoc
775303980Sngie	atf_add_test_case r_heredoc_in_cmdsub
776303980Sngie	atf_add_test_case s_heredoc_in_backticks
777303980Sngie	atf_add_test_case t_nested_cmdsubs_in_heredoc
778303980Sngie	atf_add_test_case u_nested_backticks_in_heredoc
779303980Sngie	atf_add_test_case v_cmdsub_paren_tests
780303980Sngie	atf_add_test_case w_heredoc_outside_cmdsub
781303980Sngie	atf_add_test_case x_heredoc_outside_backticks
782303980Sngie	atf_add_test_case z_absurd_heredoc_cmdsub_combos
783303980Sngie}
784