t_cmdsub.sh revision 1.4 1 # $NetBSD: t_cmdsub.sh,v 1.4 2016/04/04 12:40:13 christos Exp $
2 #
3 # Copyright (c) 2016 The NetBSD Foundation, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26 #
27 # the implementation of "sh" to test
28 : ${TEST_SH:="/bin/sh"}
29
30 #
31 # This file tests command substitutions ( `...` and $( ... ) )
32 #
33 # CAUTION:
34 # Be careful attempting running these tests outside the ATF environment
35 # Some of the tests run "rm *" in the current directory to clean up
36 # An ATF test directory should be empty already, outside ATF, anything
37
38 atf_test_case a_basic_cmdsub
39 a_basic_cmdsub_head() {
40 atf_set "descr" 'Test operation of simple $( ) substitutions'
41 }
42 a_basic_cmdsub_body() {
43 atf_check -s exit:0 -o match:'Result is true today' -e empty \
44 ${TEST_SH} -c \
45 'echo Result is $( true && echo true || echo false ) today'
46
47 atf_check -s exit:0 -o match:'Result is false today' -e empty \
48 ${TEST_SH} -c \
49 'echo Result is $( false && echo true || echo false ) today'
50
51 atf_check -s exit:0 -o match:'aaabbbccc' -e empty \
52 ${TEST_SH} -c 'echo aaa$( echo bbb )ccc'
53 atf_check -s exit:0 -o match:'aaabbb cccddd' -e empty \
54 ${TEST_SH} -c 'echo aaa$( echo bbb ccc )ddd'
55 atf_check -s exit:0 -o inline:'aaabbb cccddd\n' -e empty \
56 ${TEST_SH} -c 'echo aaa$( echo bbb; echo ccc )ddd'
57 atf_check -s exit:0 -o inline:'aaabbb\ncccddd\n' -e empty \
58 ${TEST_SH} -c 'echo "aaa$( echo bbb; echo ccc )ddd"'
59
60 atf_check -s exit:0 -o inline:'some string\n' -e empty \
61 ${TEST_SH} -c 'X=$( echo some string ); echo "$X"'
62 atf_check -s exit:0 -o inline:'weird; string *\n' -e empty \
63 ${TEST_SH} -c 'X=$( echo "weird; string *" ); echo "$X"'
64
65 rm -f * 2>/dev/null || :
66 for f in file-1 file-2
67 do
68 cp /dev/null "$f"
69 done
70
71 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
72 ${TEST_SH} -c 'echo Found $( echo * )'
73 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
74 ${TEST_SH} -c 'echo Found "$( echo * )"'
75 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
76 ${TEST_SH} -c 'echo Found $('" echo '*' )"
77 atf_check -s exit:0 -o match:'Found \*' -e empty \
78 ${TEST_SH} -c 'echo Found "$('" echo '*' "')"'
79 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
80 ${TEST_SH} -c 'echo Found $('" echo \\* )"
81 atf_check -s exit:0 -o match:'Found \*' -e empty \
82 ${TEST_SH} -c 'echo Found "$('" echo \\* )"\"
83 }
84
85 atf_test_case b_basic_backticks
86 b_basic_backticks_head() {
87 atf_set "descr" 'Test operation of old style ` ` substitutions'
88 }
89 b_basic_backticks_body() {
90 atf_check -s exit:0 -o match:'Result is true today' -e empty \
91 ${TEST_SH} -c \
92 'echo Result is `true && echo true || echo false` today'
93
94 atf_check -s exit:0 -o match:'Result is false today' -e empty \
95 ${TEST_SH} -c \
96 'echo Result is `false && echo true || echo false` today'
97
98 atf_check -s exit:0 -o match:'aaabbbccc' -e empty \
99 ${TEST_SH} -c 'echo aaa` echo bbb `ccc'
100 atf_check -s exit:0 -o match:'aaabbb cccddd' -e empty \
101 ${TEST_SH} -c 'echo aaa` echo bbb ccc `ddd'
102 atf_check -s exit:0 -o inline:'aaabbb cccddd\n' -e empty \
103 ${TEST_SH} -c 'echo aaa` echo bbb; echo ccc `ddd'
104 atf_check -s exit:0 -o inline:'aaabbb\ncccddd\n' -e empty \
105 ${TEST_SH} -c 'echo "aaa` echo bbb; echo ccc `ddd"'
106
107 atf_check -s exit:0 -o inline:'some string\n' -e empty \
108 ${TEST_SH} -c 'X=` echo some string `; echo "$X"'
109 atf_check -s exit:0 -o inline:'weird; string *\n' -e empty \
110 ${TEST_SH} -c 'X=` echo "weird; string *" `; echo "$X"'
111
112 rm -f * 2>/dev/null || :
113 for f in file-1 file-2
114 do
115 cp /dev/null "$f"
116 done
117
118 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
119 ${TEST_SH} -c 'echo Found ` echo * `'
120 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
121 ${TEST_SH} -c 'echo Found "` echo * `"'
122 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
123 ${TEST_SH} -c 'echo Found `'" echo '*' "'`'
124 atf_check -s exit:0 -o match:'Found \*' -e empty \
125 ${TEST_SH} -c 'echo Found "`'" echo '*' "'`"'
126 atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
127 ${TEST_SH} -c 'echo Found `'" echo \\* "'`'
128 atf_check -s exit:0 -o match:'Found \*' -e empty \
129 ${TEST_SH} -c 'echo Found "`'" echo \\* "'`"'
130 }
131
132 atf_test_case c_nested_cmdsub
133 c_nested_cmdsub_head() {
134 atf_set "descr" "Test that cmd substitutions can be nested"
135 }
136 c_nested_cmdsub_body() {
137 atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
138 ${TEST_SH} -c 'echo __$( echo foo$(echo bar)bletch )__'
139 atf_check -s exit:0 -o match:'_abcde_' -e empty \
140 ${TEST_SH} -c 'echo _$(echo a$(echo $(echo b)c$(echo d))e )_'
141 atf_check -s exit:0 -o match:'123454321' -e empty \
142 ${TEST_SH} -c 'echo 1$(echo 2$(echo 3$(echo 4$(echo 5)4)3)2)1'
143 }
144
145 atf_test_case d_nested_backticks
146 d_nested_backticks_head() {
147 atf_set "descr" "Tests that old style backtick cmd subs can be nested"
148 }
149 d_nested_backticks_body() {
150 atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
151 ${TEST_SH} -c 'echo __` echo foo\`echo bar\`bletch `__'
152 atf_check -s exit:0 -o match:'_abcde_' -e empty \
153 ${TEST_SH} -c \
154 'echo _`echo a\`echo \\\`echo b\\\`c\\\`echo d\\\`\`e `_'
155 atf_check -s exit:0 -o match:'123454321' -e empty \
156 ${TEST_SH} -c \
157 'echo 1`echo 2\`echo 3\\\`echo 4\\\\\\\`echo 5\\\\\\\`4\\\`3\`2`1'
158 }
159
160 atf_test_case e_perverse_mixing
161 e_perverse_mixing_head() {
162 atf_set "descr" \
163 "Checks various mixed new and old style cmd substitutions"
164 }
165 e_perverse_mixing_body() {
166 atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
167 ${TEST_SH} -c 'echo __$( echo foo`echo bar`bletch )__'
168 atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
169 ${TEST_SH} -c 'echo __` echo foo$(echo bar)bletch `__'
170 atf_check -s exit:0 -o match:'_abcde_' -e empty \
171 ${TEST_SH} -c 'echo _$(echo a`echo $(echo b)c$(echo d)`e )_'
172 atf_check -s exit:0 -o match:'_abcde_' -e empty \
173 ${TEST_SH} -c 'echo _`echo a$(echo \`echo b\`c\`echo d\`)e `_'
174 atf_check -s exit:0 -o match:'12345654321' -e empty \
175 ${TEST_SH} -c \
176 'echo 1`echo 2$(echo 3\`echo 4\\\`echo 5$(echo 6)5\\\`4\`3)2`1'
177 }
178
179 atf_test_case f_redirect_in_cmdsub
180 f_redirect_in_cmdsub_head() {
181 atf_set "descr" "Checks that redirects work in command substitutions"
182 }
183 f_redirect_in_cmdsub_body() {
184 atf_require_prog cat
185 atf_require_prog rm
186
187 rm -f file 2>/dev/null || :
188 atf_check -s exit:0 -o match:'_aa_' -e empty \
189 ${TEST_SH} -c 'echo _$( echo a$( echo b > file )a)_'
190 atf_check -s exit:0 -o match:b -e empty ${TEST_SH} -c 'cat file'
191 atf_check -s exit:0 -o match:'_aba_' -e empty \
192 ${TEST_SH} -c 'echo _$( echo a$( cat < file )a)_'
193 atf_check -s exit:0 -o match:'_aa_' -e empty \
194 ${TEST_SH} -c 'echo _$( echo a$( echo d >> file )a)_'
195 atf_check -s exit:0 -o inline:'b\nd\n' -e empty ${TEST_SH} -c 'cat file'
196 atf_check -s exit:0 -o match:'_aa_' -e match:'not error' \
197 ${TEST_SH} -c 'echo _$( echo a$( echo not error >&2 )a)_'
198 }
199
200 atf_test_case g_redirect_in_backticks
201 g_redirect_in_backticks_head() {
202 atf_set "descr" "Checks that redirects work in old style cmd sub"
203 }
204 g_redirect_in_backticks_body() {
205 atf_require_prog cat
206 atf_require_prog rm
207
208 rm -f file 2>/dev/null || :
209 atf_check -s exit:0 -o match:'_aa_' -e empty \
210 ${TEST_SH} -c 'echo _` echo a\` echo b > file \`a`_'
211 atf_check -s exit:0 -o match:b -e empty ${TEST_SH} -c 'cat file'
212 atf_check -s exit:0 -o match:'_aba_' -e empty \
213 ${TEST_SH} -c 'echo _` echo a\` cat < file \`a`_'
214 atf_check -s exit:0 -o match:'_aa_' -e empty \
215 ${TEST_SH} -c 'echo _` echo a\` echo d >> file \`a`_'
216 atf_check -s exit:0 -o inline:'b\nd\n' -e empty ${TEST_SH} -c 'cat file'
217 atf_check -s exit:0 -o match:'_aa_' -e match:'not error' \
218 ${TEST_SH} -c 'echo _` echo a\` echo not error >&2 \`a`_'
219 }
220
221 atf_test_case h_vars_in_cmdsub
222 h_vars_in_cmdsub_head() {
223 atf_set "descr" "Check that variables work in command substitutions"
224 }
225 h_vars_in_cmdsub_body() {
226 atf_check -s exit:0 -o match:'__abc__' -e empty \
227 ${TEST_SH} -c 'X=abc; echo __$( echo ${X} )__'
228 atf_check -s exit:0 -o match:'__abc__' -e empty \
229 ${TEST_SH} -c 'X=abc; echo __$( echo "${X}" )__'
230 atf_check -s exit:0 -o match:'__abc__' -e empty \
231 ${TEST_SH} -c 'X=abc; echo "__$( echo ${X} )__"'
232 atf_check -s exit:0 -o match:'__abc__' -e empty \
233 ${TEST_SH} -c 'X=abc; echo "__$( echo "${X}" )__"'
234
235 atf_check -s exit:0 -o inline:'a\n\nb\n\nc\n' -e empty \
236 ${TEST_SH} -c "for X in a '' b '' c"'; do echo $( echo "$X" ); done'
237
238 atf_check -s exit:0 -o match:'__acd__' -e empty \
239 ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X-b}${Y-c}d)__"'
240 atf_check -s exit:0 -o match:'__abcd__' -e empty \
241 ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X:-b}${Y:-c}d)__"'
242 atf_check -s exit:0 -o match:'__XYX__' -e empty \
243 ${TEST_SH} -c 'X=X; echo "__${X}$( X=Y; echo ${X} )${X}__"'
244 atf_check -s exit:0 -o match:'__def__' -e empty \
245 ${TEST_SH} -c 'X=abc; echo "__$(X=def; echo "${X}" )__"'
246 atf_check -s exit:0 -o inline:'abcdef\nabc\n' -e empty \
247 ${TEST_SH} -c 'X=abc; echo "$X$(X=def; echo ${X} )"; echo $X'
248 }
249
250 atf_test_case i_vars_in_backticks
251 i_vars_in_backticks_head() {
252 atf_set "descr" "Checks that variables work in old style cmd sub"
253 }
254 i_vars_in_backticks_body() {
255 atf_check -s exit:0 -o match:'__abc__' -e empty \
256 ${TEST_SH} -c 'X=abc; echo __` echo ${X} `__'
257 atf_check -s exit:0 -o match:'__abc__' -e empty \
258 ${TEST_SH} -c 'X=abc; echo __` echo "${X}" `__'
259 atf_check -s exit:0 -o match:'__abc__' -e empty \
260 ${TEST_SH} -c 'X=abc; echo "__` echo ${X} `__"'
261 atf_check -s exit:0 -o match:'__abc__' -e empty \
262 ${TEST_SH} -c 'X=abc; echo "__` echo \"${X}\" `__"'
263
264 atf_check -s exit:0 -o inline:'a\n\nb\n\nc\n' -e empty \
265 ${TEST_SH} -c "for X in a '' b '' c"'; do echo $( echo "$X" ); done'
266
267 atf_check -s exit:0 -o match:'__acd__' -e empty \
268 ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X-b}${Y-c}d)__"'
269 atf_check -s exit:0 -o match:'__abcd__' -e empty \
270 ${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X:-b}${Y:-c}d)__"'
271 atf_check -s exit:0 -o match:'__XYX__' -e empty \
272 ${TEST_SH} -c 'X=X; echo "__${X}$( X=Y; echo ${X} )${X}__"'
273 atf_check -s exit:0 -o inline:'abcdef\nabc\n' -e empty \
274 ${TEST_SH} -c 'X=abc; echo "$X`X=def; echo \"${X}\" `";echo $X'
275
276 # The following is nonsense, so is not included ...
277 # atf_check -s exit:0 -o match:'__abc__' -e empty \
278 # oV cV oV cV
279 # ${TEST_SH} -c 'X=abc; echo "__`X=def echo "${X}" `__"'
280 # `start in " ^ " ends, ` not yet
281 }
282
283 atf_test_case j_cmdsub_in_varexpand
284 j_cmdsub_in_varexpand_head() {
285 atf_set "descr" "Checks that command sub can be used in var expansion"
286 }
287 j_cmdsub_in_varexpand_body() {
288 atf_check -s exit:0 -o match:'foo' -e empty \
289 ${TEST_SH} -c 'X=set; echo ${X+$(echo foo)}'
290 atf_check -s exit:0 -o match:'set' -e empty \
291 ${TEST_SH} -c 'X=set; echo ${X-$(echo foo)}'
292 rm -f bar 2>/dev/null || :
293 atf_check -s exit:0 -o match:'set' -e empty \
294 ${TEST_SH} -c 'X=set; echo ${X-$(echo foo > bar)}'
295 test -f bar && atf_fail "bar should not exist, but does"
296 atf_check -s exit:0 -o inline:'\n' -e empty \
297 ${TEST_SH} -c 'X=set; echo ${X+$(echo foo > bar)}'
298 test -f bar || atf_fail "bar should exist, but does not"
299 }
300
301 atf_test_case k_backticks_in_varexpand
302 k_backticks_in_varexpand_head() {
303 atf_set "descr" "Checks that old style cmd sub works in var expansion"
304 }
305 k_backticks_in_varexpand_body() {
306 atf_check -s exit:0 -o match:'foo' -e empty \
307 ${TEST_SH} -c 'X=set; echo ${X+`echo foo`}'
308 atf_check -s exit:0 -o match:'set' -e empty \
309 ${TEST_SH} -c 'X=set; echo ${X-`echo foo`}'
310 rm -f bar 2>/dev/null || :
311 atf_check -s exit:0 -o match:'set' -e empty \
312 ${TEST_SH} -c 'X=set; echo ${X-`echo foo > bar`}'
313 test -f bar && atf_fail "bar should not exist, but does"
314 atf_check -s exit:0 -o inline:'\n' -e empty \
315 ${TEST_SH} -c 'X=set; echo ${X+`echo foo > bar`}'
316 test -f bar || atf_fail "bar should exist, but does not"
317 }
318
319 atf_test_case l_arithmetic_in_cmdsub
320 l_arithmetic_in_cmdsub_head() {
321 atf_set "descr" "Checks that arithmetic works in cmd substitutions"
322 }
323 l_arithmetic_in_cmdsub_body() {
324 atf_check -s exit:0 -o inline:'1 + 1 = 2\n' -e empty \
325 ${TEST_SH} -c 'echo 1 + 1 = $( echo $(( 1 + 1 )) )'
326 atf_check -s exit:0 -o inline:'X * Y = 6\n' -e empty \
327 ${TEST_SH} -c 'X=2; Y=3; echo X \* Y = $( echo $(( X * Y )) )'
328 atf_check -s exit:0 -o inline:'Y % X = 1\n' -e empty \
329 ${TEST_SH} -c 'X=2; Y=3; echo Y % X = $( echo $(( $Y % $X )) )'
330 }
331
332 atf_test_case m_arithmetic_in_backticks
333 m_arithmetic_in_backticks_head() {
334 atf_set "descr" "Checks that arithmetic works in old style cmd sub"
335 }
336 m_arithmetic_in_backticks_body() {
337 atf_check -s exit:0 -o inline:'2 + 3 = 5\n' -e empty \
338 ${TEST_SH} -c 'echo 2 + 3 = ` echo $(( 2 + 3 )) `'
339 atf_check -s exit:0 -o inline:'X * Y = 6\n' -e empty \
340 ${TEST_SH} -c 'X=2; Y=3; echo X \* Y = ` echo $(( X * Y )) `'
341 atf_check -s exit:0 -o inline:'Y % X = 1\n' -e empty \
342 ${TEST_SH} -c 'X=2; Y=3; echo Y % X = ` echo $(( $Y % $X )) `'
343 }
344
345 atf_test_case n_cmdsub_in_arithmetic
346 n_cmdsub_in_arithmetic_head() {
347 atf_set "descr" "Tests uses of command substitutions in arithmetic"
348 }
349 n_cmdsub_in_arithmetic_body() {
350 atf_check -s exit:0 -o inline:'7\n' -e empty \
351 ${TEST_SH} -c 'echo $(( $( echo 3 ) $( echo + ) $( echo 4 ) ))'
352 atf_check -s exit:0 -o inline:'11\n7\n18\n4\n1\n' -e empty \
353 ${TEST_SH} -c \
354 'for op in + - \* / %
355 do
356 echo $(( $( echo 9 ) $( echo "${op}" ) $( echo 2 ) ))
357 done'
358 }
359
360 atf_test_case o_backticks_in_arithmetic
361 o_backticks_in_arithmetic_head() {
362 atf_set "descr" "Tests old style cmd sub used in arithmetic"
363 }
364 o_backticks_in_arithmetic_body() {
365 atf_check -s exit:0 -o inline:'33\n' -e empty \
366 ${TEST_SH} -c 'echo $(( `echo 77` `echo -` `echo 44`))'
367 atf_check -s exit:0 -o inline:'14\n8\n33\n3\n2\n' -e empty \
368 ${TEST_SH} -c \
369 'for op in + - \* / %
370 do
371 echo $((`echo 11``echo "${op}"``echo 3`))
372 done'
373 }
374
375 atf_test_case p_cmdsub_in_heredoc
376 p_cmdsub_in_heredoc_head() {
377 atf_set "descr" "Checks that cmdsubs work inside a here document"
378 }
379 p_cmdsub_in_heredoc_body() {
380 atf_require_prog cat
381
382 atf_check -s exit:0 -o inline:'line 1+1\nline 2\nline 3\n' -e empty \
383 ${TEST_SH} -c \
384 'cat <<- EOF
385 $( echo line 1 )$( echo +1 )
386 $( echo line 2;echo line 3 )
387 EOF'
388 }
389
390 atf_test_case q_backticks_in_heredoc
391 q_backticks_in_heredoc_head() {
392 atf_set "descr" "Checks that old style cmdsubs work in here docs"
393 }
394 q_backticks_in_heredoc_body() {
395 atf_require_prog cat
396
397 atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
398 ${TEST_SH} -c \
399 'cat <<- EOF
400 `echo Mary ` `echo had a `
401 ` echo little; echo lamb `
402 EOF'
403 }
404
405 atf_test_case r_heredoc_in_cmdsub
406 r_heredoc_in_cmdsub_head() {
407 atf_set "descr" "Checks that here docs work inside cmd subs"
408 }
409 r_heredoc_in_cmdsub_body() {
410 atf_require_prog cat
411
412 atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
413 ${TEST_SH} -c 'echo "$( cat <<- \EOF
414 Mary had a
415 little
416 lamb
417 EOF
418 )"'
419
420 atf_check -s exit:0 -e empty \
421 -o inline:'Mary had 1\nlittle\nlamb\nMary had 4\nlittle\nlambs\n' \
422 ${TEST_SH} -c 'for N in 1 4; do echo "$( cat <<- EOF
423 Mary had ${N}
424 little
425 lamb$( [ $N -gt 1 ] && echo s )
426 EOF
427 )"; done'
428
429
430 atf_check -s exit:0 -o inline:'A Calculation:\n2 * 7 = 14\n' -e empty \
431 ${TEST_SH} -c 'echo "$( cat <<- EOF
432 A Calculation:
433 2 * 7 = $(( 2 * 7 ))
434 EOF
435 )"'
436 }
437
438 atf_test_case s_heredoc_in_backticks
439 s_heredoc_in_backticks_head() {
440 atf_set "descr" "Checks that here docs work inside old style cmd subs"
441 }
442 s_heredoc_in_backticks_body() {
443 atf_require_prog cat
444
445 atf_check -s exit:0 -o inline:'Mary had a little lamb\n' -e empty \
446 ${TEST_SH} -c 'echo ` cat <<- \EOF
447 Mary had a
448 little
449 lamb
450 EOF
451 `'
452
453 atf_check -s exit:0 -o inline:'A Calculation:\n17 / 3 = 5\n' -e empty \
454 ${TEST_SH} -c 'echo "` cat <<- EOF
455 A Calculation:
456 17 / 3 = $(( 17 / 3 ))
457 EOF
458 `"'
459 }
460
461 atf_test_case t_nested_cmdsubs_in_heredoc
462 t_nested_cmdsubs_in_heredoc_head() {
463 atf_set "descr" "Checks nested command substitutions in here docs"
464 }
465 t_nested_cmdsubs_in_heredoc_body() {
466 atf_require_prog cat
467 atf_require_prog rm
468
469 rm -f * 2>/dev/null || :
470 echo "Hello" > File
471
472 atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
473 ${TEST_SH} -c 'cat <<- EOF
474 $(cat File) U
475 $( V=$(cat File); echo "${V%lo}p" ) me!
476 EOF'
477
478 rm -f * 2>/dev/null || :
479 echo V>V ; echo A>A; echo R>R
480 echo Value>VAR
481
482 atf_check -s exit:0 -o inline:'$2.50\n' -e empty \
483 ${TEST_SH} -c 'cat <<- EOF
484 $(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})))
485 EOF'
486 }
487
488 atf_test_case u_nested_backticks_in_heredoc
489 u_nested_backticks_in_heredoc_head() {
490 atf_set "descr" "Checks nested old style cmd subs in here docs"
491 }
492 u_nested_backticks_in_heredoc_body() {
493 atf_require_prog cat
494 atf_require_prog rm
495
496 rm -f * 2>/dev/null || :
497 echo "Hello" > File
498
499 atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
500 ${TEST_SH} -c 'cat <<- EOF
501 `cat File` U
502 `V=\`cat File\`; echo "${V%lo}p" ` me!
503 EOF'
504
505 rm -f * 2>/dev/null || :
506 echo V>V ; echo A>A; echo R>R
507 echo Value>VAR
508
509 atf_check -s exit:0 -o inline:'$5.20\n' -e empty \
510 ${TEST_SH} -c 'cat <<- EOF
511 `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}\\\`\``
512 EOF'
513 }
514
515 atf_test_case v_cmdsub_paren_tests
516 v_cmdsub__paren_tests_head() {
517 atf_set "descr" "tests with cmdsubs containing embedded ')'"
518 }
519 v_cmdsub_paren_tests_body() {
520
521 # Tests from:
522 # http://www.in-ulm.de/~mascheck/various/cmd-subst/
523 # (slightly modified.)
524
525 atf_check -s exit:0 -o inline:'A.1\n' -e empty ${TEST_SH} -c \
526 'echo $(
527 case x in x) echo A.1;; esac
528 )'
529
530 atf_check -s exit:0 -o inline:'A.2\n' -e empty ${TEST_SH} -c \
531 'echo $(
532 case x in x) echo A.2;; esac # comment
533 )'
534
535 atf_check -s exit:0 -o inline:'A.3\n' -e empty ${TEST_SH} -c \
536 'echo $(
537 case x in (x) echo A.3;; esac
538 )'
539
540 atf_check -s exit:0 -o inline:'A.4\n' -e empty ${TEST_SH} -c \
541 'echo $(
542 case x in (x) echo A.4;; esac # comment
543 )'
544
545 atf_check -s exit:0 -o inline:'A.5\n' -e empty ${TEST_SH} -c \
546 'echo $(
547 case x in (x) echo A.5
548 esac
549 )'
550
551 atf_check -s exit:0 -o inline:'B: quoted )\n' -e empty ${TEST_SH} -c \
552 'echo $(
553 echo '\''B: quoted )'\''
554 )'
555
556 atf_check -s exit:0 -o inline:'C: comment then closing paren\n' \
557 -e empty ${TEST_SH} -c \
558 'echo $(
559 echo C: comment then closing paren # )
560 )'
561
562 atf_check -s exit:0 -o inline:'D.1: here-doc with )\n' \
563 -e empty ${TEST_SH} -c \
564 'echo $(
565 cat <<-\eof
566 D.1: here-doc with )
567 eof
568 )'
569
570 # D.2 is a bogus test.
571
572 atf_check -s exit:0 -o inline:'D.3: here-doc with \()\n' \
573 -e empty ${TEST_SH} -c \
574 'echo $(
575 cat <<-\eof
576 D.3: here-doc with \()
577 eof
578 )'
579
580 atf_check -s exit:0 -e empty \
581 -o inline:'E: here-doc terminated with a parenthesis ("academic")\n' \
582 ${TEST_SH} -c \
583 'echo $(
584 cat <<-\)
585 E: here-doc terminated with a parenthesis ("academic")
586 )
587 )'
588
589 atf_check -s exit:0 -e empty \
590 -o inline:'F.1: here-doc embed with unbal single, back- or doublequote '\''\n' \
591 ${TEST_SH} -c \
592 'echo $(
593 cat <<-"eof"
594 F.1: here-doc embed with unbal single, back- or doublequote '\''
595 eof
596 )'
597 atf_check -s exit:0 -e empty \
598 -o inline:'F.2: here-doc embed with unbal single, back- or doublequote "\n' \
599 ${TEST_SH} -c \
600 'echo $(
601 cat <<-"eof"
602 F.2: here-doc embed with unbal single, back- or doublequote "
603 eof
604 )'
605 atf_check -s exit:0 -e empty \
606 -o inline:'F.3: here-doc embed with unbal single, back- or doublequote `\n' \
607 ${TEST_SH} -c \
608 'echo $(
609 cat <<-"eof"
610 F.3: here-doc embed with unbal single, back- or doublequote `
611 eof
612 )'
613
614 atf_check -s exit:0 -e empty -o inline:'G: backslash at end of line\n' \
615 ${TEST_SH} -c \
616 'echo $(
617 echo G: backslash at end of line # \
618 )'
619
620 atf_check -s exit:0 -e empty \
621 -o inline:'H: empty command-substitution\n' \
622 ${TEST_SH} -c 'echo H: empty command-substitution $( )'
623 }
624
625 atf_test_case w_heredoc_outside_cmdsub
626 w_heredoc_outside_cmdsub_head() {
627 atf_set "descr" "Checks that here docs work inside cmd subs"
628 }
629 w_heredoc_outside_cmdsub_body() {
630 atf_require_prog cat
631
632 atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
633 ${TEST_SH} -c 'echo "$( cat <<- \EOF )"
634 Mary had a
635 little
636 lamb
637 EOF
638 '
639
640 atf_check -s exit:0 -e empty \
641 -o inline:'Mary had 1\nlittle\nlamb\nMary had 4\nlittle\nlambs\n' \
642 ${TEST_SH} -c 'for N in 1 4; do echo "$( cat <<- EOF )"
643 Mary had ${N}
644 little
645 lamb$( [ $N -gt 1 ] && echo s )
646 EOF
647 done'
648
649
650 atf_check -s exit:0 -o inline:'A Calculation:\n2 * 7 = 14\n' -e empty \
651 ${TEST_SH} -c 'echo "$( cat <<- EOF)"
652 A Calculation:
653 2 * 7 = $(( 2 * 7 ))
654 EOF
655 '
656 }
657
658 atf_test_case x_heredoc_outside_backticks
659 x_heredoc_outside_backticks_head() {
660 atf_set "descr" "Checks that here docs work inside old style cmd subs"
661 }
662 x_heredoc_outside_backticks_body() {
663 atf_require_prog cat
664
665 atf_check -s exit:0 -o inline:'Mary had a little lamb\n' -e empty \
666 ${TEST_SH} -c 'echo ` cat <<- \EOF `
667 Mary had a
668 little
669 lamb
670 EOF
671 '
672
673 atf_check -s exit:0 -o inline:'A Calculation:\n17 / 3 = 5\n' -e empty \
674 ${TEST_SH} -c 'echo "` cat <<- EOF `"
675 A Calculation:
676 17 / 3 = $(( 17 / 3 ))
677 EOF
678 '
679 }
680
681 atf_test_case t_nested_cmdsubs_in_heredoc
682 t_nested_cmdsubs_in_heredoc_head() {
683 atf_set "descr" "Checks nested command substitutions in here docs"
684 }
685 t_nested_cmdsubs_in_heredoc_body() {
686 atf_require_prog cat
687 atf_require_prog rm
688
689 rm -f * 2>/dev/null || :
690 echo "Hello" > File
691
692 atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
693 ${TEST_SH} -c 'cat <<- EOF
694 $(cat File) U
695 $( V=$(cat File); echo "${V%lo}p" ) me!
696 EOF'
697
698 rm -f * 2>/dev/null || :
699 echo V>V ; echo A>A; echo R>R
700 echo Value>VAR
701
702 atf_check -s exit:0 -o inline:'$2.50\n' -e empty \
703 ${TEST_SH} -c 'cat <<- EOF
704 $(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})))
705 EOF'
706 }
707
708 atf_test_case z_absurd_heredoc_cmdsub_combos
709 z_absurd_heredoc_cmdsub_combos_head() {
710 atf_set "descr" "perverse and unusual cmd substitutions & more"
711 }
712 z_absurd_heredoc_cmdsub_combos_body() {
713
714 echo "Help!" > help
715
716 # This version works in NetBSD (& FreeBSD)'s sh (and most others)
717 atf_check -s exit:0 -o inline:'Help!\nMe 2\n' -e empty ${TEST_SH} -c '
718 cat <<- EOF
719 $(
720 cat <<- STOP
721 $(
722 cat `echo help`
723 )
724 STOP
725 )
726 $(
727 cat <<- END 4<<-TRASH
728 Me $(( 1 + 1 ))
729 END
730 This is unused noise!
731 TRASH
732 )
733 EOF
734 '
735
736 # atf_expect_fail "PR bin/50993 - heredoc parsing done incorrectly"
737 atf_check -s exit:0 -o inline:'Help!\nMe 2\n' -e empty ${TEST_SH} -c '
738 cat <<- EOF
739 $(
740 cat << STOP
741 $(
742 cat `echo help`
743 )
744 STOP
745 )
746 $(
747 cat <<- END 4<<TRASH
748 Me $(( 1 + 1 ))
749 END
750 This is unused noise!
751 TRASH
752 )
753 EOF
754 '
755 }
756
757 atf_init_test_cases() {
758 atf_add_test_case a_basic_cmdsub
759 atf_add_test_case b_basic_backticks
760 atf_add_test_case c_nested_cmdsub
761 atf_add_test_case d_nested_backticks
762 atf_add_test_case e_perverse_mixing
763 atf_add_test_case f_redirect_in_cmdsub
764 atf_add_test_case g_redirect_in_backticks
765 atf_add_test_case h_vars_in_cmdsub
766 atf_add_test_case i_vars_in_backticks
767 atf_add_test_case j_cmdsub_in_varexpand
768 atf_add_test_case k_backticks_in_varexpand
769 atf_add_test_case l_arithmetic_in_cmdsub
770 atf_add_test_case m_arithmetic_in_backticks
771 atf_add_test_case n_cmdsub_in_arithmetic
772 atf_add_test_case o_backticks_in_arithmetic
773 atf_add_test_case p_cmdsub_in_heredoc
774 atf_add_test_case q_backticks_in_heredoc
775 atf_add_test_case r_heredoc_in_cmdsub
776 atf_add_test_case s_heredoc_in_backticks
777 atf_add_test_case t_nested_cmdsubs_in_heredoc
778 atf_add_test_case u_nested_backticks_in_heredoc
779 atf_add_test_case v_cmdsub_paren_tests
780 atf_add_test_case w_heredoc_outside_cmdsub
781 atf_add_test_case x_heredoc_outside_backticks
782 atf_add_test_case z_absurd_heredoc_cmdsub_combos
783 }
784