t_here.sh revision 1.2 1 # $NetBSD: t_here.sh,v 1.2 2016/02/29 23:52:53 christos Exp $
2 #
3 # Copyright (c) 2007 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 nl='
31 '
32
33 check()
34 {
35 fail=false
36 TEMP_FILE=$( mktemp OUT.XXXXXX )
37
38 # our local shell (ATF_SHELL) better do quoting correctly...
39 # some of the tests expect us to expand $nl internally...
40 CMD="nl='${nl}'; $1"
41
42 echo "${CMD}" >/tmp/CMD
43 rm -f trace.*
44 result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
45 STATUS=$?
46
47 if [ -s "${O_FILE}" ]; then
48 echo >&2 "unexpected shell output noise on stdout"
49 cat "${O_FILE}" >&2
50 fail=true
51 fi
52
53 if [ "${STATUS}" -ne "$3" ]; then
54 echo >&2 "expected exit code $3, got ${STATUS}"
55
56 # don't actually fail just because of wrong exit code
57 # unless we either expected, or received "good"
58 case "$3/${STATUS}" in
59 (*/0|0/*) fail=true;;
60 esac
61 fi
62
63 if [ "$3" -eq 0 ]; then
64 if [ -s "${TEMP_FILE}" ]; then
65 echo >&2 "Messages produced on stderr unexpected..."
66 cat "${TEMP_FILE}" >&2
67 fail=true
68 fi
69 else
70 if ! [ -s "${TEMP_FILE}" ]; then
71 echo >&2 "Expected messages on stderr, nothing produced"
72 fail=true
73 fi
74 fi
75 rm -f "${TEMP_FILE}"
76
77 # Remove newlines (use local shell for this)
78 oifs="$IFS"
79 IFS="$nl"
80 result="$(echo $result)"
81 IFS="$oifs"
82 if [ "$2" != "$result" ]
83 then
84 echo >&2 "Expected output '$2', received '$result'"
85 fail=true
86 fi
87
88 $fail && atf_fail "test of '$1' failed"
89 return 0
90 }
91
92 atf_test_case do_simple
93 do_simple_head() {
94 atf_set "descr" "Basic tests for here documents"
95 }
96 do_simple_body() {
97 y=x
98
99 IFS=
100 check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
101 check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
102
103 check "y=${y};"'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
104 'text' 0
105 check "y=${y};"'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
106 'te${y}t' 0
107 check "y=${y};"'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
108 'te${y}t' 0
109 check "y=${y};"'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
110 'te${y}t' 0
111
112 # check that quotes in the here doc survive and cause no problems
113 check "cat <<EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
114 check "cat <<\EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
115 check "cat <<'EOF'${nl}te'xt${nl}EOF$nl" "te'xt" 0
116 check "cat <<EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
117 check "cat <<\EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
118 check "cat <<'EOF'${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
119 check "cat <<'EO'F${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
120
121 check "y=${y};"'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' \
122 'te'"'"'xt' 0
123 check "y=${y};"'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' \
124 'te'"''"'xt' 0
125
126 # note that the blocks of empty space in the following must
127 # be entirely tab characters, no spaces.
128
129 check 'x=`cat <<EOF'"$nl text${nl}EOF$nl"'`; echo "$x"' \
130 ' text' 0
131 check 'x=`cat <<-EOF'"$nl text${nl}EOF$nl"'`; echo $x' \
132 'text' 0
133 check 'x=`cat <<-EOF'"${nl}text${nl} EOF$nl"'`; echo $x' \
134 'text' 0
135 check 'x=`cat <<-\EOF'"$nl text${nl} EOF$nl"'`; echo $x' \
136 'text' 0
137 check 'x=`cat <<- "EOF"'"$nl text${nl}EOF$nl"'`; echo $x' \
138 'text' 0
139 check 'x=`cat <<- '"'EOF'${nl}text${nl} EOF$nl"'`; echo $x' \
140 'text' 0
141 }
142
143 atf_test_case incomplete
144 incomplete_head() {
145 atf_set "descr" "Basic tests for incomplete here documents"
146 }
147 incomplete_body() {
148 check 'cat <<EOF' '' 2
149 check 'cat <<- EOF' '' 2
150 check 'cat <<\EOF' '' 2
151 check 'cat <<- \EOF' '' 2
152
153 check 'cat <<EOF'"${nl}" '' 2
154 check 'cat <<- EOF'"${nl}" '' 2
155 check 'cat <<'"'EOF'${nl}" '' 2
156 check 'cat <<- "EOF"'"${nl}" '' 2
157
158 check 'cat << EOF'"${nl}${nl}" '' 2
159 check 'cat <<-EOF'"${nl}${nl}" '' 2
160 check 'cat << '"'EOF'${nl}${nl}" '' 2
161 check 'cat <<-"EOF"'"${nl}${nl}" '' 2
162
163 check 'cat << EOF'"${nl}"'line 1'"${nl}" '' 2
164 check 'cat <<-EOF'"${nl}"' line 1'"${nl}" '' 2
165 check 'cat << EOF'"${nl}"'line 1'"${nl}"' line 2'"${nl}" '' 2
166 check 'cat <<-EOF'"${nl}"' line 1'"${nl}"'line 2'"${nl}" '' 2
167
168 check 'cat << EOF'"${nl}line 1${nl}${nl}line3${nl}${nl}5!${nl}" '' 2
169 }
170
171 atf_test_case multiple
172 multiple_head() {
173 atf_set "descr" "Tests for multiple here documents for one cmd"
174 }
175 multiple_body() {
176 check \
177 "(cat ; cat <&3) <<EOF0 3<<EOF3${nl}STDIN${nl}EOF0${nl}-3-${nl}EOF3${nl}" \
178 'STDIN -3-' 0
179
180 check "(read line; echo \"\$line\"; cat <<EOF1; echo \"\$line\") <<EOF2
181 The File
182 EOF1
183 The Line
184 EOF2
185 " 'The Line The File The Line' 0
186
187 check "(read line; echo \"\$line\"; cat <<EOF; echo \"\$line\") <<EOF
188 The File
189 EOF
190 The Line
191 EOF
192 " 'The Line The File The Line' 0
193
194 }
195
196 atf_test_case viscious
197 viscious_head() {
198 atf_set "descr" "Tests for obscure and obnoxious uses of here docs"
199 }
200 viscious_body() {
201
202 cat <<- \END_SCRIPT > script
203 cat <<ONE && cat \
204 <<TWO
205 a
206 ONE
207 b
208 TWO
209 END_SCRIPT
210
211 atf_check -s exit:0 -o inline:'a\nb\n' -e empty ${TEST_SH} script
212
213 # This next one is causing discussion currently (late Feb 2016)
214 # amongst stds writers & implementors. Consequently we
215 # will not check what it produces. The eventual result
216 # seems unlikely to be what we currently output, which
217 # is:
218 # :echo line 1
219 # B:echo line 2)" && prefix DASH_CODE <<DASH_CODE
220 # B:echo line 3
221 # line 4
222 # line 5
223 #
224 # The likely intended output is ...
225 #
226 # A:echo line 3
227 # B:echo line 1
228 # line 2
229 # DASH_CODE:echo line 4)"
230 # DASH_CODE:echo line 5
231 #
232 # The difference is explained by differeng opinions on just
233 # when processing of a here doc should start
234
235 cat <<- \END_SCRIPT > script
236 prefix() { sed -e "s/^/$1:/"; }
237 DASH_CODE() { :; }
238
239 prefix A <<XXX && echo "$(prefix B <<XXX
240 echo line 1
241 XXX
242 echo line 2)" && prefix DASH_CODE <<DASH_CODE
243 echo line 3
244 XXX
245 echo line 4)"
246 echo line 5
247 DASH_CODE
248 END_SCRIPT
249
250 # we will just verify that the shell can parse the
251 # script somehow, and doesn't fall over completely...
252
253 atf_check -s exit:0 -o ignore -e empty ${TEST+SH} script
254 }
255
256 atf_init_test_cases() {
257 atf_add_test_case do_simple
258 atf_add_test_case incomplete
259 atf_add_test_case multiple # multiple << operators on one cmd
260 atf_add_test_case viscious # evil test from the austin-l list...
261 }
262