t_here.sh revision 1.8 1 1.8 kre # $NetBSD: t_here.sh,v 1.8 2021/09/09 00:04:51 kre Exp $
2 1.1 jruoho #
3 1.1 jruoho # Copyright (c) 2007 The NetBSD Foundation, Inc.
4 1.1 jruoho # All rights reserved.
5 1.1 jruoho #
6 1.1 jruoho # Redistribution and use in source and binary forms, with or without
7 1.1 jruoho # modification, are permitted provided that the following conditions
8 1.1 jruoho # are met:
9 1.1 jruoho # 1. Redistributions of source code must retain the above copyright
10 1.1 jruoho # notice, this list of conditions and the following disclaimer.
11 1.1 jruoho # 2. Redistributions in binary form must reproduce the above copyright
12 1.1 jruoho # notice, this list of conditions and the following disclaimer in the
13 1.1 jruoho # documentation and/or other materials provided with the distribution.
14 1.1 jruoho #
15 1.1 jruoho # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 1.1 jruoho # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 1.1 jruoho # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 1.1 jruoho # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 1.1 jruoho # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 1.1 jruoho # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 1.1 jruoho # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 1.1 jruoho # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 1.1 jruoho # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 1.1 jruoho # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 jruoho # POSSIBILITY OF SUCH DAMAGE.
26 1.1 jruoho #
27 1.2 christos # the implementation of "sh" to test
28 1.2 christos : ${TEST_SH:="/bin/sh"}
29 1.1 jruoho
30 1.1 jruoho nl='
31 1.1 jruoho '
32 1.1 jruoho
33 1.5 christos reset()
34 1.5 christos {
35 1.5 christos TEST_NUM=0
36 1.5 christos TEST_FAILURES=''
37 1.5 christos TEST_FAIL_COUNT=0
38 1.5 christos TEST_ID="$1"
39 1.5 christos }
40 1.5 christos
41 1.1 jruoho check()
42 1.1 jruoho {
43 1.2 christos fail=false
44 1.2 christos TEMP_FILE=$( mktemp OUT.XXXXXX )
45 1.5 christos TEST_NUM=$(( $TEST_NUM + 1 ))
46 1.2 christos
47 1.2 christos # our local shell (ATF_SHELL) better do quoting correctly...
48 1.2 christos # some of the tests expect us to expand $nl internally...
49 1.2 christos CMD="nl='${nl}'; $1"
50 1.2 christos
51 1.2 christos result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
52 1.2 christos STATUS=$?
53 1.2 christos
54 1.2 christos if [ "${STATUS}" -ne "$3" ]; then
55 1.5 christos echo >&2 "[$TEST_NUM] expected exit code $3, got ${STATUS}"
56 1.2 christos
57 1.2 christos # don't actually fail just because of wrong exit code
58 1.2 christos # unless we either expected, or received "good"
59 1.2 christos case "$3/${STATUS}" in
60 1.2 christos (*/0|0/*) fail=true;;
61 1.2 christos esac
62 1.2 christos fi
63 1.2 christos
64 1.2 christos if [ "$3" -eq 0 ]; then
65 1.2 christos if [ -s "${TEMP_FILE}" ]; then
66 1.5 christos echo >&2 \
67 1.5 christos "[$TEST_NUM] Messages produced on stderr unexpected..."
68 1.2 christos cat "${TEMP_FILE}" >&2
69 1.2 christos fail=true
70 1.2 christos fi
71 1.2 christos else
72 1.2 christos if ! [ -s "${TEMP_FILE}" ]; then
73 1.5 christos echo >&2 \
74 1.5 christos "[$TEST_NUM] Expected messages on stderr, nothing produced"
75 1.2 christos fail=true
76 1.2 christos fi
77 1.2 christos fi
78 1.2 christos rm -f "${TEMP_FILE}"
79 1.2 christos
80 1.2 christos # Remove newlines (use local shell for this)
81 1.7 kre result="$(
82 1.7 kre IFS="$nl"
83 1.7 kre set -f
84 1.7 kre set -- $result
85 1.7 kre IFS=' '
86 1.7 kre printf %s "$*"
87 1.7 kre )"
88 1.1 jruoho if [ "$2" != "$result" ]
89 1.1 jruoho then
90 1.5 christos echo >&2 "[$TEST_NUM] Expected output '$2', received '$result'"
91 1.2 christos fail=true
92 1.1 jruoho fi
93 1.2 christos
94 1.6 christos if $fail
95 1.6 christos then
96 1.6 christos echo >&2 "[$TEST_NUM] Full command: <<${CMD}>>"
97 1.6 christos fi
98 1.6 christos
99 1.5 christos $fail && test -n "$TEST_ID" && {
100 1.5 christos TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+
101 1.5 christos }${TEST_ID}[$TEST_NUM]: test of '$1' failed";
102 1.5 christos TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
103 1.5 christos return 0
104 1.5 christos }
105 1.5 christos $fail && atf_fail "Test[$TEST_NUM] of '$1' failed"
106 1.2 christos return 0
107 1.1 jruoho }
108 1.1 jruoho
109 1.5 christos results()
110 1.5 christos {
111 1.5 christos test -z "${TEST_ID}" && return 0
112 1.5 christos test -z "${TEST_FAILURES}" && return 0
113 1.5 christos
114 1.5 christos echo >&2 "=========================================="
115 1.5 christos echo >&2 "While testing '${TEST_ID}'"
116 1.5 christos echo >&2 " - - - - - - - - - - - - - - - - -"
117 1.5 christos echo >&2 "${TEST_FAILURES}"
118 1.5 christos atf_fail \
119 1.5 christos "Test ${TEST_ID}: $TEST_FAIL_COUNT subtests (of $TEST_NUM) failed - see stderr"
120 1.5 christos }
121 1.5 christos
122 1.2 christos atf_test_case do_simple
123 1.2 christos do_simple_head() {
124 1.1 jruoho atf_set "descr" "Basic tests for here documents"
125 1.1 jruoho }
126 1.2 christos do_simple_body() {
127 1.1 jruoho y=x
128 1.1 jruoho
129 1.5 christos reset 'simple'
130 1.5 christos IFS=' '
131 1.2 christos check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
132 1.2 christos check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
133 1.2 christos
134 1.2 christos check "y=${y};"'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
135 1.2 christos 'text' 0
136 1.2 christos check "y=${y};"'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
137 1.2 christos 'te${y}t' 0
138 1.2 christos check "y=${y};"'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
139 1.2 christos 'te${y}t' 0
140 1.2 christos check "y=${y};"'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
141 1.2 christos 'te${y}t' 0
142 1.2 christos
143 1.2 christos # check that quotes in the here doc survive and cause no problems
144 1.2 christos check "cat <<EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
145 1.2 christos check "cat <<\EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
146 1.2 christos check "cat <<'EOF'${nl}te'xt${nl}EOF$nl" "te'xt" 0
147 1.2 christos check "cat <<EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
148 1.2 christos check "cat <<\EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
149 1.2 christos check "cat <<'EOF'${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
150 1.2 christos check "cat <<'EO'F${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
151 1.2 christos
152 1.2 christos check "y=${y};"'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' \
153 1.2 christos 'te'"'"'xt' 0
154 1.2 christos check "y=${y};"'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' \
155 1.2 christos 'te'"''"'xt' 0
156 1.2 christos
157 1.2 christos # note that the blocks of empty space in the following must
158 1.2 christos # be entirely tab characters, no spaces.
159 1.2 christos
160 1.2 christos check 'x=`cat <<EOF'"$nl text${nl}EOF$nl"'`; echo "$x"' \
161 1.2 christos ' text' 0
162 1.2 christos check 'x=`cat <<-EOF'"$nl text${nl}EOF$nl"'`; echo $x' \
163 1.2 christos 'text' 0
164 1.2 christos check 'x=`cat <<-EOF'"${nl}text${nl} EOF$nl"'`; echo $x' \
165 1.2 christos 'text' 0
166 1.2 christos check 'x=`cat <<-\EOF'"$nl text${nl} EOF$nl"'`; echo $x' \
167 1.2 christos 'text' 0
168 1.2 christos check 'x=`cat <<- "EOF"'"$nl text${nl}EOF$nl"'`; echo $x' \
169 1.2 christos 'text' 0
170 1.2 christos check 'x=`cat <<- '"'EOF'${nl}text${nl} EOF$nl"'`; echo $x' \
171 1.2 christos 'text' 0
172 1.5 christos results
173 1.5 christos }
174 1.5 christos
175 1.5 christos atf_test_case end_markers
176 1.5 christos end_markers_head() {
177 1.5 christos atf_set "descr" "Tests for various end markers of here documents"
178 1.5 christos }
179 1.5 christos end_markers_body() {
180 1.5 christos
181 1.5 christos reset 'end_markers'
182 1.6 christos for end in EOF 1 \! '$$$' "string " a\\\ a\\\ \ '&' '' ' ' ' ' \
183 1.6 christos --STRING-- . '~~~' ')' '(' '#' '()' '(\)' '(\/)' '--' '\' '{' '}' \
184 1.5 christos VERYVERYVERYVERYLONGLONGLONGin_fact_absurdly_LONG_LONG_HERE_DOCUMENT_TERMINATING_MARKER_THAT_goes_On_forever_and_ever_and_ever...
185 1.5 christos do
186 1.5 christos # check unquoted end markers
187 1.5 christos case "${end}" in
188 1.6 christos ('' | *[' ()\$&#*~']* ) ;; # skip unquoted endmark test for these
189 1.5 christos (*) check \
190 1.6 christos 'x=$(cat << '"${end}${nl}text${nl}${end}${nl}"'); printf %s "$x"' 'text' 0
191 1.5 christos ;;
192 1.5 christos esac
193 1.5 christos
194 1.5 christos # and quoted end markers
195 1.5 christos check \
196 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end}${nl}"'); printf %s "$x"' 'text' 0
197 1.5 christos
198 1.5 christos # and see what happens if we encounter "almost" an end marker
199 1.5 christos case "${#end}" in
200 1.5 christos (0|1) ;; # too short to try truncation tests
201 1.5 christos (*) check \
202 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}${nl}${end}${nl}"'); printf %s "$x"' \
203 1.5 christos "text ${end%?}" 0
204 1.5 christos check \
205 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end#?}${nl}${end}${nl}"'); printf %s "$x"' \
206 1.5 christos "text ${end#?}" 0
207 1.5 christos check \
208 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}+${nl}${end}${nl}"');printf %s "$x"' \
209 1.5 christos "text ${end%?}+" 0
210 1.5 christos ;;
211 1.5 christos esac
212 1.5 christos
213 1.5 christos # or something that is a little longer
214 1.5 christos check \
215 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end}x${nl}${end}${nl}"'); printf %s "$x"' \
216 1.5 christos "text ${end}x" 0
217 1.5 christos check \
218 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}!${end}${nl}${end}${nl}"'); printf %s "$x"' \
219 1.5 christos "text !${end}" 0
220 1.5 christos
221 1.5 christos # or which does not begin at start of line
222 1.5 christos check \
223 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl} ${end}${nl}${end}${nl}"'); printf %s "$x"' \
224 1.5 christos "text ${end}" 0
225 1.5 christos check \
226 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl} ${end}${nl}${end}${nl}"'); printf %s "$x"' \
227 1.5 christos "text ${end}" 0
228 1.5 christos
229 1.5 christos # or end at end of line
230 1.5 christos check \
231 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end} ${nl}${end}${nl}"'); printf %s "$x"' \
232 1.5 christos "text ${end} " 0
233 1.5 christos
234 1.5 christos # or something that is correct much of the way, but then...
235 1.5 christos
236 1.5 christos case "${#end}" in
237 1.5 christos (0) ;; # cannot test this one
238 1.5 christos (1) check \
239 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end}${end}${nl}${end}${nl}"'); printf %s "$x"' \
240 1.5 christos "text ${end}${end}" 0
241 1.5 christos ;;
242 1.5 christos (2-7) pfx="${end%?}"
243 1.5 christos check \
244 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end}${pfx}${nl}${end}${nl}"'); printf %s "$x"' \
245 1.5 christos "text ${end}${pfx}" 0
246 1.5 christos check \
247 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); printf %s "$x"' \
248 1.5 christos "text ${pfx}${end}" 0
249 1.5 christos ;;
250 1.5 christos (*) pfx=${end%??????}; sfx=${end#??????}
251 1.5 christos check \
252 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${end}${sfx}${nl}${end}${nl}"'); printf %s "$x"' \
253 1.5 christos "text ${end}${sfx}" 0
254 1.5 christos check \
255 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); printf %s "$x"' \
256 1.5 christos "text ${pfx}${end}" 0
257 1.5 christos check \
258 1.6 christos 'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${sfx}${nl}${end}${nl}"'); printf %s "$x"' \
259 1.5 christos "text ${pfx}${sfx}" 0
260 1.5 christos ;;
261 1.5 christos esac
262 1.5 christos done
263 1.5 christos
264 1.5 christos # Add striptabs tests (in similar way) here one day...
265 1.5 christos
266 1.5 christos results
267 1.2 christos }
268 1.2 christos
269 1.2 christos atf_test_case incomplete
270 1.2 christos incomplete_head() {
271 1.2 christos atf_set "descr" "Basic tests for incomplete here documents"
272 1.2 christos }
273 1.2 christos incomplete_body() {
274 1.5 christos reset incomplete
275 1.5 christos
276 1.2 christos check 'cat <<EOF' '' 2
277 1.2 christos check 'cat <<- EOF' '' 2
278 1.2 christos check 'cat <<\EOF' '' 2
279 1.2 christos check 'cat <<- \EOF' '' 2
280 1.2 christos
281 1.2 christos check 'cat <<EOF'"${nl}" '' 2
282 1.2 christos check 'cat <<- EOF'"${nl}" '' 2
283 1.2 christos check 'cat <<'"'EOF'${nl}" '' 2
284 1.2 christos check 'cat <<- "EOF"'"${nl}" '' 2
285 1.2 christos
286 1.2 christos check 'cat << EOF'"${nl}${nl}" '' 2
287 1.2 christos check 'cat <<-EOF'"${nl}${nl}" '' 2
288 1.2 christos check 'cat << '"'EOF'${nl}${nl}" '' 2
289 1.2 christos check 'cat <<-"EOF"'"${nl}${nl}" '' 2
290 1.2 christos
291 1.2 christos check 'cat << EOF'"${nl}"'line 1'"${nl}" '' 2
292 1.2 christos check 'cat <<-EOF'"${nl}"' line 1'"${nl}" '' 2
293 1.2 christos check 'cat << EOF'"${nl}"'line 1'"${nl}"' line 2'"${nl}" '' 2
294 1.2 christos check 'cat <<-EOF'"${nl}"' line 1'"${nl}"'line 2'"${nl}" '' 2
295 1.2 christos
296 1.2 christos check 'cat << EOF'"${nl}line 1${nl}${nl}line3${nl}${nl}5!${nl}" '' 2
297 1.5 christos
298 1.5 christos results
299 1.5 christos }
300 1.5 christos
301 1.5 christos atf_test_case lineends
302 1.5 christos lineends_head() {
303 1.5 christos atf_set "descr" "Tests for line endings in here documents"
304 1.5 christos }
305 1.5 christos lineends_body() {
306 1.5 christos reset lineends
307 1.5 christos
308 1.5 christos # note that "check" removes newlines from stdout before comparing.
309 1.5 christos # (they become blanks, provided there is something before & after)
310 1.5 christos
311 1.5 christos check 'cat << \echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" '\' 0
312 1.5 christos check 'cat << echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" 'echo' 0
313 1.5 christos check 'cat << echo'"${nl}"'\\'"${nl}echo${nl}echo${nl}" '\' 0
314 1.5 christos
315 1.5 christos check 'X=3; cat << ec\ho'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
316 1.5 christos '$X\' 0
317 1.5 christos check 'X=3; cat << echo'"${nl}"'$X'"${nl}echo${nl}echo${nl}" \
318 1.5 christos '3' 0
319 1.5 christos check 'X=3; cat << echo'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
320 1.5 christos '' 0
321 1.5 christos check 'X=3; cat << echo'"${nl}"'${X}\'"${nl}echo${nl}echo${nl}" \
322 1.5 christos '3echo' 0
323 1.5 christos check 'X=3; cat << echo'"${nl}"'\$X\'"${nl}echo${nl}echo${nl}" \
324 1.5 christos '$Xecho' 0
325 1.5 christos check 'X=3; cat << echo'"${nl}"'\\$X \'"${nl}echo${nl}echo${nl}" \
326 1.5 christos '\3 echo' 0
327 1.5 christos
328 1.5 christos check \
329 1.5 christos 'cat << "echo"'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
330 1.5 christos 'line1\ line2\' 0
331 1.5 christos check \
332 1.5 christos 'cat << echo'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
333 1.5 christos 'line1line2echo' 0
334 1.5 christos
335 1.5 christos results
336 1.2 christos }
337 1.2 christos
338 1.2 christos atf_test_case multiple
339 1.2 christos multiple_head() {
340 1.5 christos atf_set "descr" "Tests for multiple here documents on one cmd line"
341 1.2 christos }
342 1.2 christos multiple_body() {
343 1.5 christos reset multiple
344 1.5 christos
345 1.2 christos check \
346 1.2 christos "(cat ; cat <&3) <<EOF0 3<<EOF3${nl}STDIN${nl}EOF0${nl}-3-${nl}EOF3${nl}" \
347 1.2 christos 'STDIN -3-' 0
348 1.2 christos
349 1.2 christos check "(read line; echo \"\$line\"; cat <<EOF1; echo \"\$line\") <<EOF2
350 1.2 christos The File
351 1.2 christos EOF1
352 1.2 christos The Line
353 1.2 christos EOF2
354 1.2 christos " 'The Line The File The Line' 0
355 1.2 christos
356 1.2 christos check "(read line; echo \"\$line\"; cat <<EOF; echo \"\$line\") <<EOF
357 1.2 christos The File
358 1.2 christos EOF
359 1.2 christos The Line
360 1.2 christos EOF
361 1.2 christos " 'The Line The File The Line' 0
362 1.2 christos
363 1.5 christos check "V=1; W=2; cat <<-1; cat <<2; cat <<- 3; cat <<'4';"' cat <<\5
364 1.5 christos $V
365 1.5 christos $W
366 1.5 christos 3
367 1.5 christos 4
368 1.5 christos 5
369 1.5 christos 1
370 1.5 christos 2
371 1.5 christos 5
372 1.5 christos 4*$W+\$V
373 1.5 christos 3
374 1.5 christos $W
375 1.5 christos 1
376 1.5 christos 2
377 1.5 christos 3
378 1.5 christos 4
379 1.5 christos 7+$V
380 1.5 christos $W+6
381 1.5 christos 5
382 1.5 christos ' '1 2 3 4 5 5 4*2+$V $W 1 2 3 7+$V $W+6' 0
383 1.5 christos
384 1.5 christos results
385 1.5 christos }
386 1.5 christos
387 1.5 christos atf_test_case nested
388 1.5 christos nested_head() {
389 1.5 christos atf_set "descr" "Tests for nested here documents for one cmd"
390 1.5 christos }
391 1.5 christos nested_body() {
392 1.5 christos reset nested
393 1.5 christos
394 1.5 christos check \
395 1.5 christos 'cat << EOF1'"${nl}"'$(cat << EOF2'"${nl}LINE${nl}EOF2${nl}"')'"${nl}EOF1${nl}"\
396 1.5 christos 'LINE' 0
397 1.5 christos
398 1.5 christos # This next one fails ... and correctly, so we will omit it (bad test)
399 1.5 christos # Reasoning is that the correct data "$(cat << EOF2)\nLINE\nEOF2\n" is
400 1.5 christos # collected for the outer (EOF1) heredoc, when that is parsed, it looks
401 1.5 christos # like
402 1.5 christos # $(cat <<EOF2)
403 1.5 christos # LINE
404 1.5 christos # EOF2
405 1.5 christos # which looks like a good command - except it is being parsed in "heredoc"
406 1.5 christos # syntax, which means it is enclosed in double quotes, which means that
407 1.5 christos # the newline after the ')' in the first line is not a newline token, but
408 1.5 christos # just a character. The EOF2 heredoc cannot start until after the next
409 1.5 christos # newline token, of which there are none here... LINE and EOF2 are just
410 1.5 christos # more data in the outer EOF1 heredoc for its "cat" command to read & write.
411 1.5 christos #
412 1.5 christos # The previous sub-test works because there the \n comes inside the
413 1.5 christos # $( ), and in there, the outside quoting rules are suspended, and it
414 1.5 christos # all starts again - so that \n is a newline token, and the EOF2 heredoc
415 1.5 christos # is processed.
416 1.5 christos #
417 1.5 christos # check \
418 1.5 christos # 'cat << EOF1'"${nl}"'$(cat << EOF2 )'"${nl}LINE${nl}EOF2${nl}EOF1${nl}" \
419 1.5 christos # 'LINE' 0
420 1.5 christos
421 1.5 christos L='cat << EOF1'"${nl}"'LINE1$(cat << EOF2'"${nl}"
422 1.5 christos L="${L}"'LINE2$(cat << EOF3'"${nl}"
423 1.5 christos L="${L}"'LINE3$(cat << EOF4'"${nl}"
424 1.5 christos L="${L}"'LINE4$(cat << EOF5'"${nl}"
425 1.5 christos L="${L}LINE5${nl}EOF5${nl})4${nl}EOF4${nl})3${nl}"
426 1.5 christos L="${L}EOF3${nl})2${nl}EOF2${nl})1${nl}EOF1${nl}"
427 1.5 christos
428 1.5 christos # That mess is ...
429 1.5 christos #
430 1.5 christos # cat <<EOF1
431 1.5 christos # LINE1$(cat << EOF2
432 1.5 christos # LINE2$(cat << EOF3
433 1.5 christos # LINE3$(cat << EOF4
434 1.5 christos # LINE4$(cat << EOF5
435 1.5 christos # LINE5
436 1.5 christos # EOF5
437 1.5 christos # )4
438 1.5 christos # EOF4
439 1.5 christos # )3
440 1.5 christos # EOF3
441 1.5 christos # )2
442 1.5 christos # EOF2
443 1.5 christos # )1
444 1.5 christos # EOF1
445 1.5 christos
446 1.5 christos check "${L}" 'LINE1LINE2LINE3LINE4LINE54321' 0
447 1.5 christos
448 1.5 christos results
449 1.5 christos }
450 1.5 christos
451 1.5 christos atf_test_case quoting
452 1.5 christos quoting_head() {
453 1.5 christos atf_set "descr" "Tests for use of quotes inside here documents"
454 1.5 christos }
455 1.5 christos quoting_body() {
456 1.5 christos reset quoting
457 1.5 christos
458 1.5 christos check 'X=!; cat <<- E\0F
459 1.5 christos <'\''"'\'' \\$X\$X "'\''" \\>
460 1.5 christos E0F
461 1.5 christos ' '<'\''"'\'' \\$X\$X "'\''" \\>' 0
462 1.5 christos
463 1.5 christos check 'X=!; cat <<- E0F
464 1.5 christos <'\''"'\'' \\$X\$X "'\''" \\>
465 1.5 christos E0F
466 1.5 christos ' '<'\''"'\'' \!$X "'\''" \>' 0
467 1.5 christos
468 1.5 christos check 'cat <<- END
469 1.5 christos $( echo "'\''" ) $( echo '\''"'\'' ) $( echo \\ )
470 1.5 christos END
471 1.5 christos ' "' \" \\" 0
472 1.5 christos
473 1.5 christos check 'X=12345; Y="string1 line1?-line2"; Z=; unset W; cat <<-EOF
474 1.5 christos ${#X}${Z:-${Y}}${W+junk}${Y%%l*}${Y#*\?}
475 1.5 christos "$Z"'\''$W'\'' ${Y%" "*} $(( X + 54321 ))
476 1.5 christos EOF
477 1.5 christos ' '5string1 line1?-line2string1 -line2 ""'\'\'' string1 66666' 0
478 1.5 christos
479 1.7 kre # check that \ only quotes the magic chars, otherwise is retained
480 1.7 kre check 'p=A; cat <<-EOF
481 1.7 kre ${p+\%$p\%}
482 1.7 kre ${p+%$p%}
483 1.7 kre EOF
484 1.7 kre ' '\%A\% %A%' 0
485 1.7 kre
486 1.7 kre # and check that " is not magic, so \ does not quote it
487 1.7 kre check 'p=A; cat <<-EOF
488 1.7 kre ${p+\"$p\"}
489 1.7 kre ${p+"$p"}
490 1.7 kre EOF
491 1.7 kre ' '\"A\" "A"' 0
492 1.7 kre
493 1.7 kre # except in a ${var%<word>} word, base syntax reapplies, and
494 1.7 kre # there quotes are magic again
495 1.7 kre check 'p=ABCD; cat <<-EOF
496 1.7 kre ${p%B?D}
497 1.7 kre ${p%B\?D}
498 1.7 kre ${p%"BCD"}
499 1.7 kre "${p%??}"
500 1.7 kre ${p#"${p%??}"}
501 1.7 kre "${p#"${p%?"?"}"}"
502 1.7 kre EOF
503 1.7 kre ' 'A ABCD A "AB" CD ""' 0
504 1.7 kre
505 1.7 kre check 'p=AB??; cat <<-EOF
506 1.7 kre ${p%B?D}
507 1.7 kre ${p%B\??}
508 1.7 kre ${p%"B??"}
509 1.7 kre "${p%??}"
510 1.7 kre ${p#"${p%??}"}
511 1.7 kre "${p#"${p%?"?"}"}"
512 1.7 kre EOF
513 1.7 kre ' 'AB?? A A "AB" ?? "??"' 0
514 1.7 kre
515 1.5 christos results
516 1.5 christos }
517 1.5 christos
518 1.5 christos atf_test_case side_effects
519 1.5 christos side_effects_head() {
520 1.5 christos atf_set "descr" "Tests how side effects in here documents are handled"
521 1.5 christos }
522 1.5 christos side_effects_body() {
523 1.5 christos
524 1.5 christos atf_check -s exit:0 -o inline:'2\n1\n' -e empty ${TEST_SH} -c '
525 1.5 christos unset X
526 1.5 christos cat <<-EOF
527 1.5 christos ${X=2}
528 1.5 christos EOF
529 1.5 christos echo "${X-1}"
530 1.5 christos '
531 1.2 christos }
532 1.2 christos
533 1.8 kre # The following tests a problem reported on the austin-list 2021-09-08
534 1.8 kre # by oguzismailuysal (at] gmail.com ... it affected all ash derived shells
535 1.8 kre atf_test_case hard_cases
536 1.8 kre hard_cases_head() {
537 1.8 kre atf_set "descr" \
538 1.8 kre "Tests here docs in positions that have confised our parser"
539 1.8 kre }
540 1.8 kre hard_cases_body() {
541 1.8 kre
542 1.8 kre atf_check -s exit:0 -o inline:'xxx\n' -e empty ${TEST_SH} -c '
543 1.8 kre : <<- do | for x in xxx
544 1.8 kre do
545 1.8 kre do echo $x
546 1.8 kre done'
547 1.8 kre
548 1.8 kre atf_check -s exit:0 -o inline:'xxx\n' -e empty ${TEST_SH} -c '
549 1.8 kre set -- xxx
550 1.8 kre : <<- done | for x in xxx
551 1.8 kre done
552 1.8 kre do echo $x
553 1.8 kre done'
554 1.8 kre
555 1.8 kre atf_check -s exit:0 -o inline:'xxx\n' -e empty ${TEST_SH} -c '
556 1.8 kre : <<- in | case xxx
557 1.8 kre in
558 1.8 kre in xxx) echo xxx;;
559 1.8 kre esac'
560 1.8 kre }
561 1.8 kre
562 1.3 christos atf_test_case vicious
563 1.3 christos vicious_head() {
564 1.2 christos atf_set "descr" "Tests for obscure and obnoxious uses of here docs"
565 1.2 christos }
566 1.3 christos vicious_body() {
567 1.5 christos reset
568 1.2 christos
569 1.2 christos cat <<- \END_SCRIPT > script
570 1.2 christos cat <<ONE && cat \
571 1.2 christos <<TWO
572 1.2 christos a
573 1.2 christos ONE
574 1.2 christos b
575 1.2 christos TWO
576 1.2 christos END_SCRIPT
577 1.2 christos
578 1.2 christos atf_check -s exit:0 -o inline:'a\nb\n' -e empty ${TEST_SH} script
579 1.2 christos
580 1.2 christos # This next one is causing discussion currently (late Feb 2016)
581 1.2 christos # amongst stds writers & implementors. Consequently we
582 1.2 christos # will not check what it produces. The eventual result
583 1.2 christos # seems unlikely to be what we currently output, which
584 1.2 christos # is:
585 1.3 christos # A:echo line 1
586 1.2 christos # B:echo line 2)" && prefix DASH_CODE <<DASH_CODE
587 1.2 christos # B:echo line 3
588 1.2 christos # line 4
589 1.2 christos # line 5
590 1.2 christos #
591 1.2 christos # The likely intended output is ...
592 1.2 christos #
593 1.2 christos # A:echo line 3
594 1.2 christos # B:echo line 1
595 1.2 christos # line 2
596 1.2 christos # DASH_CODE:echo line 4)"
597 1.2 christos # DASH_CODE:echo line 5
598 1.2 christos #
599 1.5 christos # The difference is explained by differing opinions on just
600 1.2 christos # when processing of a here doc should start
601 1.2 christos
602 1.2 christos cat <<- \END_SCRIPT > script
603 1.2 christos prefix() { sed -e "s/^/$1:/"; }
604 1.2 christos DASH_CODE() { :; }
605 1.2 christos
606 1.2 christos prefix A <<XXX && echo "$(prefix B <<XXX
607 1.2 christos echo line 1
608 1.2 christos XXX
609 1.2 christos echo line 2)" && prefix DASH_CODE <<DASH_CODE
610 1.2 christos echo line 3
611 1.2 christos XXX
612 1.2 christos echo line 4)"
613 1.2 christos echo line 5
614 1.2 christos DASH_CODE
615 1.2 christos END_SCRIPT
616 1.1 jruoho
617 1.2 christos # we will just verify that the shell can parse the
618 1.2 christos # script somehow, and doesn't fall over completely...
619 1.1 jruoho
620 1.5 christos atf_check -s exit:0 -o ignore -e empty ${TEST_SH} script
621 1.1 jruoho }
622 1.1 jruoho
623 1.1 jruoho atf_init_test_cases() {
624 1.5 christos atf_add_test_case do_simple # not worthy of a comment
625 1.5 christos atf_add_test_case end_markers # the mundane, the weird, the bizarre
626 1.5 christos atf_add_test_case incomplete # where the end marker isn't...
627 1.5 christos atf_add_test_case lineends # test weird line endings in heredocs
628 1.2 christos atf_add_test_case multiple # multiple << operators on one cmd
629 1.5 christos atf_add_test_case nested # here docs inside here docs
630 1.5 christos atf_add_test_case quoting # stuff quoted inside
631 1.5 christos atf_add_test_case side_effects # here docs that modify environment
632 1.8 kre atf_add_test_case hard_cases # here doc bodies appearing mid command
633 1.3 christos atf_add_test_case vicious # evil test from the austin-l list...
634 1.1 jruoho }
635