t_option.sh revision 1.6 1 1.6 kre # $NetBSD: t_option.sh,v 1.6 2017/11/16 19:41:41 kre Exp $
2 1.1 christos #
3 1.1 christos # Copyright (c) 2016 The NetBSD Foundation, Inc.
4 1.1 christos # All rights reserved.
5 1.1 christos #
6 1.1 christos # Redistribution and use in source and binary forms, with or without
7 1.1 christos # modification, are permitted provided that the following conditions
8 1.1 christos # are met:
9 1.1 christos # 1. Redistributions of source code must retain the above copyright
10 1.1 christos # notice, this list of conditions and the following disclaimer.
11 1.1 christos # 2. Redistributions in binary form must reproduce the above copyright
12 1.1 christos # notice, this list of conditions and the following disclaimer in the
13 1.1 christos # documentation and/or other materials provided with the distribution.
14 1.1 christos #
15 1.1 christos # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 1.1 christos # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 1.1 christos # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 1.1 christos # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 1.1 christos # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 1.1 christos # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 1.1 christos # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 1.1 christos # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 1.1 christos # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 1.1 christos # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 christos # POSSIBILITY OF SUCH DAMAGE.
26 1.1 christos #
27 1.1 christos # the implementation of "sh" to test
28 1.1 christos : ${TEST_SH:="/bin/sh"}
29 1.1 christos
30 1.1 christos # The standard
31 1.1 christos # http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
32 1.1 christos # says:
33 1.1 christos # ...[lots]
34 1.1 christos
35 1.1 christos test_option_on_off()
36 1.1 christos {
37 1.1 christos atf_require_prog tr
38 1.1 christos
39 1.1 christos for opt
40 1.1 christos do
41 1.1 christos # t is needed, as inside $()` $- appears to lose
42 1.1 christos # the 'e' option if it happened to already be
43 1.1 christos # set. Must check if that is what should
44 1.1 christos # happen, but that is a different issue.
45 1.1 christos
46 1.1 christos test -z "${opt}" && continue
47 1.1 christos
48 1.1 christos # if we are playing with more that one option at a
49 1.1 christos # time, the code below requires that we start with no
50 1.1 christos # options set, or it will mis-diagnose the situation
51 1.1 christos CLEAR=''
52 1.1 christos test "${#opt}" -gt 1 &&
53 1.1 christos CLEAR='xx="$-" && xx=$(echo "$xx" | tr -d cs) && test -n "$xx" && set +"$xx";'
54 1.1 christos
55 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
56 1.1 christos "opt=${opt}"'
57 1.1 christos x() {
58 1.1 christos echo "ERROR: Unable to $1 option $2" >&2
59 1.1 christos exit 1
60 1.1 christos }
61 1.1 christos s() {
62 1.1 christos set -"$1"
63 1.1 christos t="$-"
64 1.1 christos x=$(echo "$t" | tr -d "$1")
65 1.1 christos test "$t" = "$x" && x set "$1"
66 1.1 christos return 0
67 1.1 christos }
68 1.1 christos c() {
69 1.1 christos set +"$1"
70 1.1 christos t="$-"
71 1.1 christos x=$(echo "$t" | tr -d "$1")
72 1.1 christos test "$t" != "$x" && x clear "$1"
73 1.1 christos return 0
74 1.1 christos }
75 1.1 christos '"${CLEAR}"'
76 1.1 christos
77 1.1 christos # if we do not do this, -x tracing splatters stderr
78 1.1 christos # for some shells, -v does as well (is that correct?)
79 1.1 christos case "${opt}" in
80 1.6 kre (*[xXv]*) exec 2>/dev/null;;
81 1.1 christos esac
82 1.1 christos
83 1.1 christos o="$-"
84 1.1 christos x=$(echo "$o" | tr -d "$opt")
85 1.1 christos
86 1.1 christos if [ "$o" = "$x" ]; then # option was off
87 1.1 christos s "${opt}"
88 1.1 christos c "${opt}"
89 1.1 christos else
90 1.1 christos c "${opt}"
91 1.1 christos s "${opt}"
92 1.1 christos fi
93 1.1 christos '
94 1.1 christos done
95 1.1 christos }
96 1.1 christos
97 1.1 christos test_optional_on_off()
98 1.1 christos {
99 1.1 christos RET=0
100 1.1 christos OPTS=
101 1.1 christos for opt
102 1.1 christos do
103 1.1 christos test "${opt}" = n && continue
104 1.2 christos ${TEST_SH} -c "set -${opt}" 2>/dev/null &&
105 1.1 christos OPTS="${OPTS} ${opt}" || RET=1
106 1.1 christos done
107 1.1 christos
108 1.1 christos test -n "${OPTS}" && test_option_on_off ${OPTS}
109 1.1 christos
110 1.1 christos return "${RET}"
111 1.1 christos }
112 1.1 christos
113 1.1 christos atf_test_case set_a
114 1.1 christos set_a_head() {
115 1.1 christos atf_set "descr" "Tests that 'set -a' turns on all var export " \
116 1.1 christos "and that it behaves as defined by the standard"
117 1.1 christos }
118 1.1 christos set_a_body() {
119 1.1 christos atf_require_prog env
120 1.1 christos atf_require_prog grep
121 1.1 christos
122 1.1 christos test_option_on_off a
123 1.1 christos
124 1.1 christos # without -a, new variables should not be exported (so grep "fails")
125 1.2 christos atf_check -s exit:1 -o empty -e empty ${TEST_SH} -ce \
126 1.1 christos 'unset VAR; set +a; VAR=value; env | grep "^VAR="'
127 1.1 christos
128 1.1 christos # with -a, they should be
129 1.2 christos atf_check -s exit:0 -o match:VAR=value -e empty ${TEST_SH} -ce \
130 1.1 christos 'unset VAR; set -a; VAR=value; env | grep "^VAR="'
131 1.1 christos }
132 1.1 christos
133 1.1 christos atf_test_case set_C
134 1.1 christos set_C_head() {
135 1.1 christos atf_set "descr" "Tests that 'set -C' turns on no clobber mode " \
136 1.1 christos "and that it behaves as defined by the standard"
137 1.1 christos }
138 1.1 christos set_C_body() {
139 1.1 christos atf_require_prog ls
140 1.1 christos
141 1.1 christos test_option_on_off C
142 1.1 christos
143 1.1 christos # Check that the environment to use for the tests is sane ...
144 1.1 christos # we assume current dir is a new tempory directory & is empty
145 1.1 christos
146 1.1 christos test -z "$(ls)" || atf_skip "Test execution directory not clean"
147 1.1 christos test -c "/dev/null" || atf_skip "Problem with /dev/null"
148 1.1 christos
149 1.1 christos echo Dummy_Content > Junk_File
150 1.1 christos echo Precious_Content > Important_File
151 1.1 christos
152 1.1 christos # Check that we can redirect onto file when -C is not set
153 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
154 1.1 christos '
155 1.1 christos D=$(ls -l Junk_File) || exit 1
156 1.1 christos set +C
157 1.1 christos echo "Overwrite it now" > Junk_File
158 1.1 christos A=$(ls -l Junk_File) || exit 1
159 1.1 christos test "${A}" != "${D}"
160 1.1 christos '
161 1.1 christos
162 1.1 christos # Check that we cannot redirect onto file when -C is set
163 1.2 christos atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} -c \
164 1.1 christos '
165 1.1 christos D=$(ls -l Important_File) || exit 1
166 1.1 christos set -C
167 1.1 christos echo "Fail to Overwrite it now" > Important_File
168 1.1 christos A=$(ls -l Important_File) || exit 1
169 1.1 christos test "${A}" = "${D}"
170 1.1 christos '
171 1.1 christos
172 1.1 christos # Check that we can append to file, even when -C is set
173 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
174 1.1 christos '
175 1.1 christos D=$(ls -l Junk_File) || exit 1
176 1.1 christos set -C
177 1.1 christos echo "Append to it now" >> Junk_File
178 1.1 christos A=$(ls -l Junk_File) || exit 1
179 1.1 christos test "${A}" != "${D}"
180 1.1 christos '
181 1.1 christos
182 1.1 christos # Check that we abort on attempt to redirect onto file when -Ce is set
183 1.2 christos atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
184 1.1 christos '
185 1.1 christos set -Ce
186 1.1 christos echo "Fail to Overwrite it now" > Important_File
187 1.1 christos echo "Should not reach this point"
188 1.1 christos '
189 1.1 christos
190 1.1 christos # Last check that we can override -C for when we really need to
191 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
192 1.1 christos '
193 1.1 christos D=$(ls -l Junk_File) || exit 1
194 1.1 christos set -C
195 1.1 christos echo "Change the poor bugger again" >| Junk_File
196 1.1 christos A=$(ls -l Junk_File) || exit 1
197 1.1 christos test "${A}" != "${D}"
198 1.1 christos '
199 1.1 christos }
200 1.1 christos
201 1.1 christos atf_test_case set_e
202 1.1 christos set_e_head() {
203 1.1 christos atf_set "descr" "Tests that 'set -e' turns on error detection " \
204 1.1 christos "and that a simple case behaves as defined by the standard"
205 1.1 christos }
206 1.1 christos set_e_body() {
207 1.1 christos test_option_on_off e
208 1.1 christos
209 1.1 christos # Check that -e does nothing if no commands fail
210 1.1 christos atf_check -s exit:0 -o match:I_am_OK -e empty \
211 1.2 christos ${TEST_SH} -c \
212 1.1 christos 'false; printf "%s" I_am; set -e; true; printf "%s\n" _OK'
213 1.1 christos
214 1.1 christos # and that it (silently, but with exit status) aborts if cmd fails
215 1.1 christos atf_check -s not-exit:0 -o match:I_am -o not-match:Broken -e empty \
216 1.2 christos ${TEST_SH} -c \
217 1.1 christos 'false; printf "%s" I_am; set -e; false; printf "%s\n" _Broken'
218 1.1 christos
219 1.1 christos # same, except -e this time is on from the beginning
220 1.1 christos atf_check -s not-exit:0 -o match:I_am -o not-match:Broken -e empty \
221 1.2 christos ${TEST_SH} -ec 'printf "%s" I_am; false; printf "%s\n" _Broken'
222 1.1 christos
223 1.1 christos # More checking of -e in other places, there is lots to deal with.
224 1.1 christos }
225 1.1 christos
226 1.1 christos atf_test_case set_f
227 1.1 christos set_f_head() {
228 1.1 christos atf_set "descr" "Tests that 'set -f' turns off pathname expansion " \
229 1.1 christos "and that it behaves as defined by the standard"
230 1.1 christos }
231 1.1 christos set_f_body() {
232 1.1 christos atf_require_prog ls
233 1.1 christos
234 1.1 christos test_option_on_off f
235 1.1 christos
236 1.1 christos # Check that the environment to use for the tests is sane ...
237 1.1 christos # we assume current dir is a new tempory directory & is empty
238 1.1 christos
239 1.1 christos test -z "$(ls)" || atf_skip "Test execution directory not clean"
240 1.1 christos
241 1.1 christos # we will assume that atf will clean up this junk directory
242 1.1 christos # when we are done. But for testing pathname expansion
243 1.1 christos # we need files
244 1.1 christos
245 1.1 christos for f in a b c d e f aa ab ac ad ae aaa aab aac aad aba abc bbb ccc
246 1.1 christos do
247 1.1 christos echo "$f" > "$f"
248 1.1 christos done
249 1.1 christos
250 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -ec \
251 1.1 christos 'X=$(echo b*); Y=$(echo b*); test "${X}" != "a*";
252 1.1 christos test "${X}" = "${Y}"'
253 1.1 christos
254 1.1 christos # now test expansion is different when -f is set
255 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -ec \
256 1.1 christos 'X=$(echo b*); Y=$(set -f; echo b*); test "${X}" != "${Y}"'
257 1.1 christos }
258 1.1 christos
259 1.1 christos atf_test_case set_n
260 1.1 christos set_n_head() {
261 1.1 christos atf_set "descr" "Tests that 'set -n' supresses command execution " \
262 1.1 christos "and that it behaves as defined by the standard"
263 1.1 christos }
264 1.1 christos set_n_body() {
265 1.1 christos # pointless to test this, if it turns on, it stays on...
266 1.1 christos # test_option_on_off n
267 1.1 christos # so just allow the tests below to verify it can be turned on
268 1.1 christos
269 1.1 christos # nothing should be executed, hence no output...
270 1.1 christos atf_check -s exit:0 -o empty -e empty \
271 1.2 christos ${TEST_SH} -enc 'echo ABANDON HOPE; echo ALL YE; echo ...'
272 1.1 christos
273 1.1 christos # this is true even when the "commands" do not exist
274 1.1 christos atf_check -s exit:0 -o empty -e empty \
275 1.2 christos ${TEST_SH} -enc 'ERR; FAIL; ABANDON HOPE'
276 1.1 christos
277 1.2 christos # but if there is a syntax error, it should be detected (w or w/o -e)
278 1.1 christos atf_check -s not-exit:0 -o empty -e not-empty \
279 1.2 christos ${TEST_SH} -enc 'echo JUMP; for frogs swim; echo in puddles'
280 1.2 christos atf_check -s not-exit:0 -o empty -e not-empty \
281 1.2 christos ${TEST_SH} -nc 'echo ABANDON HOPE; echo "ALL YE; echo ...'
282 1.2 christos atf_check -s not-exit:0 -o empty -e not-empty \
283 1.2 christos ${TEST_SH} -enc 'echo ABANDON HOPE;; echo ALL YE; echo ...'
284 1.2 christos atf_check -s not-exit:0 -o empty -e not-empty \
285 1.2 christos ${TEST_SH} -nc 'do YOU ABANDON HOPE; for all eternity?'
286 1.1 christos
287 1.2 christos # now test enabling -n in the middle of a script
288 1.2 christos # note that once turned on, it cannot be turned off again.
289 1.2 christos #
290 1.2 christos # omit more complex cases, as those can send some shells
291 1.2 christos # into infinite loops, and believe it or not, that might be OK!
292 1.2 christos
293 1.2 christos atf_check -s exit:0 -o match:first -o not-match:second -e empty \
294 1.2 christos ${TEST_SH} -c 'echo first; set -n; echo second'
295 1.2 christos atf_check -s exit:0 -o match:first -o not-match:third -e empty \
296 1.2 christos ${TEST_SH} -c 'echo first; set -n; echo second; set +n; echo third'
297 1.2 christos atf_check -s exit:0 -o inline:'a\nb\n' -e empty \
298 1.2 christos ${TEST_SH} -c 'for x in a b c d
299 1.2 christos do
300 1.2 christos case "$x" in
301 1.2 christos a);; b);; c) set -n;; d);;
302 1.2 christos esac
303 1.2 christos printf "%s\n" "$x"
304 1.2 christos done'
305 1.2 christos
306 1.2 christos # This last one is a bit more complex to explain, so I will not try
307 1.2 christos
308 1.2 christos # First, we need to know what signal number is used for SIGUSR1 on
309 1.2 christos # the local (testing) system (signal number is $(( $XIT - 128 )) )
310 1.2 christos
311 1.2 christos # this will take slightly over 1 second elapsed time (the sleep 1)
312 1.2 christos # The "10" for the first sleep just needs to be something big enough
313 1.2 christos # that the rest of the commands have time to complete, even on
314 1.2 christos # very slow testing systems. 10 should be enough. Otherwise irrelevant
315 1.2 christos
316 1.2 christos # The shell will usually blather to stderr about the sleep 10 being
317 1.2 christos # killed, but it affects nothing, so just allow it to cry.
318 1.2 christos
319 1.2 christos (sleep 10 & sleep 1; kill -USR1 $!; wait $!)
320 1.2 christos XIT="$?"
321 1.2 christos
322 1.2 christos # The exit value should be an integer > 128 and < 256 (often 158)
323 1.2 christos # If it is not just skip the test
324 1.2 christos
325 1.2 christos # If we do run the test, it should take (slightly over) either 1 or 2
326 1.2 christos # seconds to complete, depending upon the shell being tested.
327 1.2 christos
328 1.2 christos case "${XIT}" in
329 1.2 christos ( 129 | 1[3-9][0-9] | 2[0-4][0-9] | 25[0-5] )
330 1.2 christos
331 1.2 christos # The script below should exit with the same code - no output
332 1.2 christos
333 1.2 christos # Or that is the result that seems best explanable.
334 1.2 christos # "set -n" in uses like this is not exactly well defined...
335 1.2 christos
336 1.2 christos # This script comes from a member of the austin group
337 1.2 christos # (they author changes to the posix shell spec - and more.)
338 1.2 christos # The author is also an (occasional?) NetBSD user.
339 1.2 christos atf_check -s exit:${XIT} -o empty -e empty ${TEST_SH} -c '
340 1.2 christos trap "set -n" USR1
341 1.2 christos { sleep 1; kill -USR1 $$; sleep 1; } &
342 1.2 christos false
343 1.2 christos wait && echo t || echo f
344 1.2 christos wait
345 1.2 christos echo foo
346 1.2 christos '
347 1.2 christos ;;
348 1.2 christos esac
349 1.1 christos }
350 1.1 christos
351 1.1 christos atf_test_case set_u
352 1.1 christos set_u_head() {
353 1.1 christos atf_set "descr" "Tests that 'set -u' turns on unset var detection " \
354 1.1 christos "and that it behaves as defined by the standard"
355 1.1 christos }
356 1.1 christos set_u_body() {
357 1.1 christos test_option_on_off u
358 1.1 christos
359 1.4 kre unset ENV # make sure there is nothing there to cause problems
360 1.4 kre
361 1.1 christos # first make sure it is OK to unset an unset variable
362 1.2 christos atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
363 1.1 christos 'unset _UNSET_VARIABLE_; echo OK'
364 1.1 christos # even if -u is set
365 1.2 christos atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -cue \
366 1.1 christos 'unset _UNSET_VARIABLE_; echo OK'
367 1.1 christos
368 1.1 christos # and that without -u accessing an unset variable is harmless
369 1.2 christos atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
370 1.1 christos 'unset X; echo ${X}; echo OK'
371 1.1 christos # and that the unset variable test expansion works properly
372 1.2 christos atf_check -s exit:0 -o match:OKOK -e empty ${TEST_SH} -ce \
373 1.1 christos 'unset X; printf "%s" ${X-OK}; echo OK'
374 1.1 christos
375 1.1 christos # Next test that with -u set, the shell aborts on access to unset var
376 1.1 christos # do not use -e, want to make sure it is -u that causes abort
377 1.2 christos atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
378 1.1 christos 'unset X; set -u; echo ${X}; echo ERR'
379 1.1 christos # quoting should make no difference...
380 1.2 christos atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
381 1.1 christos 'unset X; set -u; echo "${X}"; echo ERR'
382 1.1 christos
383 1.1 christos # Now a bunch of accesses to unset vars, with -u, in ways that are OK
384 1.2 christos atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
385 1.1 christos 'unset X; set -u; echo ${X-GOOD}; echo OK'
386 1.2 christos atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
387 1.1 christos 'unset X; set -u; echo ${X-OK}'
388 1.1 christos atf_check -s exit:0 -o not-match:ERR -o match:OK -e empty \
389 1.2 christos ${TEST_SH} -ce 'unset X; set -u; echo ${X+ERR}; echo OK'
390 1.1 christos
391 1.1 christos # and some more ways that are not OK
392 1.2 christos atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
393 1.1 christos 'unset X; set -u; echo ${X#foo}; echo ERR'
394 1.2 christos atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
395 1.1 christos 'unset X; set -u; echo ${X%%bar}; echo ERR'
396 1.1 christos
397 1.1 christos # lastly, just while we are checking unset vars, test aborts w/o -u
398 1.2 christos atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
399 1.1 christos 'unset X; echo ${X?}; echo ERR'
400 1.1 christos atf_check -s not-exit:0 -o not-match:ERR -e match:X_NOT_SET \
401 1.2 christos ${TEST_SH} -c 'unset X; echo ${X?X_NOT_SET}; echo ERR'
402 1.1 christos }
403 1.1 christos
404 1.1 christos atf_test_case set_v
405 1.1 christos set_v_head() {
406 1.1 christos atf_set "descr" "Tests that 'set -v' turns on input read echoing " \
407 1.1 christos "and that it behaves as defined by the standard"
408 1.1 christos }
409 1.1 christos set_v_body() {
410 1.1 christos test_option_on_off v
411 1.1 christos
412 1.1 christos # check that -v does nothing if no later input line is read
413 1.1 christos atf_check -s exit:0 \
414 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
415 1.1 christos -e empty \
416 1.2 christos ${TEST_SH} -ec 'printf "%s" OK; set -v; echo OK; exit 0'
417 1.1 christos
418 1.1 christos # but that it does when there are multiple lines
419 1.3 christos cat <<- 'EOF' |
420 1.3 christos set -v
421 1.3 christos printf %s OK
422 1.3 christos echo OK
423 1.3 christos exit 0
424 1.3 christos EOF
425 1.1 christos atf_check -s exit:0 \
426 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
427 1.1 christos -e match:printf -e match:OK -e match:echo \
428 1.3 christos -e not-match:set ${TEST_SH}
429 1.1 christos
430 1.1 christos # and that it can be disabled again
431 1.3 christos cat <<- 'EOF' |
432 1.3 christos set -v
433 1.3 christos printf %s OK
434 1.3 christos set +v
435 1.3 christos echo OK
436 1.3 christos exit 0
437 1.3 christos EOF
438 1.1 christos atf_check -s exit:0 \
439 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
440 1.1 christos -e match:printf -e match:OK -e not-match:echo \
441 1.3 christos ${TEST_SH}
442 1.1 christos
443 1.1 christos # and lastly, that shell keywords do get output when "read"
444 1.3 christos cat <<- 'EOF' |
445 1.3 christos set -v
446 1.3 christos for i in 111 222 333
447 1.3 christos do
448 1.3 christos printf %s $i
449 1.3 christos done
450 1.3 christos exit 0
451 1.3 christos EOF
452 1.1 christos atf_check -s exit:0 \
453 1.1 christos -o match:111222333 -o not-match:printf \
454 1.1 christos -o not-match:for -o not-match:do -o not-match:done \
455 1.1 christos -e match:printf -e match:111 -e not-match:111222 \
456 1.1 christos -e match:for -e match:do -e match:done \
457 1.3 christos ${TEST_SH}
458 1.1 christos }
459 1.1 christos
460 1.1 christos atf_test_case set_x
461 1.1 christos set_x_head() {
462 1.1 christos atf_set "descr" "Tests that 'set -x' turns on command exec logging " \
463 1.1 christos "and that it behaves as defined by the standard"
464 1.1 christos }
465 1.1 christos set_x_body() {
466 1.1 christos test_option_on_off x
467 1.1 christos
468 1.1 christos # check that cmd output appears after -x is enabled
469 1.1 christos atf_check -s exit:0 \
470 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
471 1.1 christos -e not-match:printf -e match:OK -e match:echo \
472 1.2 christos ${TEST_SH} -ec 'printf "%s" OK; set -x; echo OK; exit 0'
473 1.1 christos
474 1.1 christos # and that it stops again afer -x is disabled
475 1.1 christos atf_check -s exit:0 \
476 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
477 1.1 christos -e match:printf -e match:OK -e not-match:echo \
478 1.2 christos ${TEST_SH} -ec 'set -x; printf "%s" OK; set +x; echo OK; exit 0'
479 1.1 christos
480 1.1 christos # also check that PS4 is output correctly
481 1.1 christos atf_check -s exit:0 \
482 1.1 christos -o match:OK -o not-match:echo \
483 1.1 christos -e match:OK -e match:Run:echo \
484 1.2 christos ${TEST_SH} -ec 'PS4=Run:; set -x; echo OK; exit 0'
485 1.1 christos
486 1.1 christos return 0
487 1.1 christos
488 1.1 christos # This one seems controversial... I suspect it is NetBSD's sh
489 1.1 christos # that is wrong to not output "for" "while" "if" ... etc
490 1.1 christos
491 1.1 christos # and lastly, that shell keywords do not get output when "executed"
492 1.1 christos atf_check -s exit:0 \
493 1.1 christos -o match:111222333 -o not-match:printf \
494 1.1 christos -o not-match:for \
495 1.1 christos -e match:printf -e match:111 -e not-match:111222 \
496 1.1 christos -e not-match:for -e not-match:do -e not-match:done \
497 1.2 christos ${TEST_SH} -ec \
498 1.1 christos 'set -x; for i in 111 222 333; do printf "%s" $i; done; echo; exit 0'
499 1.1 christos }
500 1.1 christos
501 1.6 kre atf_test_case set_X
502 1.6 kre set_X_head() {
503 1.6 kre atf_set "descr" "Tests that 'set -X' turns on command exec logging " \
504 1.6 kre "and that it enables set -x and retains a single fd"
505 1.6 kre }
506 1.6 kre set_X_body() {
507 1.6 kre
508 1.6 kre # First we need to verify that $TEST_SH supports -X
509 1.6 kre test_optional_on_off X ||
510 1.6 kre atf_skip "$TEST_SH does not support -X"
511 1.6 kre
512 1.6 kre # and that the -X it implements is the -X we expect
513 1.6 kre $TEST_SH -c 'exec 2>/dev/null;
514 1.6 kre set +x; set -X;
515 1.6 kre case "$-" in (*x*) exit 0;; esac;
516 1.6 kre exit 1' ||
517 1.6 kre atf_skip "$TEST_SH supports -X but not 'the' -X"
518 1.6 kre
519 1.6 kre # Above has already tested that set -X => set -x
520 1.6 kre # Now test that set +X => set +x
521 1.6 kre # and that set -x and set +x do not affect -X
522 1.6 kre
523 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
524 1.6 kre 'set -x; set +X; case "$-" in (*x*) echo FAIL; exit 1;; esac'
525 1.6 kre
526 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
527 1.6 kre 'set -X; set +x;
528 1.6 kre case "$-" in (*x*) echo FAIL; exit 1;; esac
529 1.6 kre case "$-" in (*X*) exit 0;; esac; echo ERROR; exit 2'
530 1.6 kre
531 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
532 1.6 kre 'set -X; set +x; set -x;
533 1.6 kre case "$-" in (*x*X*|*X*x*) exit 0;; esac; echo ERROR; exit 2'
534 1.6 kre
535 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
536 1.6 kre 'set +X; set -x;
537 1.6 kre case "$-" in (*X*) echo FAIL; exit 1;; esac
538 1.6 kre case "$-" in (*x*) exit 0;; esac; echo ERROR; exit 2'
539 1.6 kre
540 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
541 1.6 kre 'set +X; set -x; set +x;
542 1.6 kre case "$-" in (*[xX]*) echo FAULT; exit 3;; esac'
543 1.6 kre
544 1.6 kre # The following just verify regular tracing using -X instead of -x
545 1.6 kre # These are the same tests as the -x test (set_x) performs.
546 1.6 kre
547 1.6 kre # check that cmd output appears after -X is enabled
548 1.6 kre atf_check -s exit:0 \
549 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
550 1.6 kre -e not-match:printf -e match:OK -e match:echo \
551 1.6 kre ${TEST_SH} -ec 'printf "%s" OK; set -X; echo OK; exit 0'
552 1.6 kre
553 1.6 kre # and that it stops again afer -X is disabled
554 1.6 kre atf_check -s exit:0 \
555 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
556 1.6 kre -e match:printf -e match:OK -e not-match:echo \
557 1.6 kre ${TEST_SH} -ec 'set -X; printf "%s" OK; set +X; echo OK; exit 0'
558 1.6 kre
559 1.6 kre # also check that PS4 is output correctly
560 1.6 kre atf_check -s exit:0 \
561 1.6 kre -o match:OK -o not-match:echo \
562 1.6 kre -e match:OK -e match:Run:echo \
563 1.6 kre ${TEST_SH} -ec 'PS4=Run:; set -X; echo OK; exit 0'
564 1.6 kre
565 1.6 kre # end copies of -x tests ...
566 1.6 kre
567 1.6 kre # now check that we can move stderr around without affecting -X output
568 1.6 kre
569 1.6 kre atf_check -s exit:0 \
570 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
571 1.6 kre -e match:printf -e match:OK -e match:echo \
572 1.6 kre ${TEST_SH} -ecX 'printf "%s" OK; exec 2>/dev/null; echo OK'
573 1.6 kre atf_check -s exit:0 \
574 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
575 1.6 kre -e match:printf -e match:OK -e match:echo \
576 1.6 kre ${TEST_SH} -ecX 'printf "%s" OK; exec 2>&1; echo OK'
577 1.6 kre atf_check -s exit:0 \
578 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
579 1.6 kre -e match:printf -e match:OK -e match:echo \
580 1.6 kre ${TEST_SH} -ecX 'printf "%s" OK; exec 2>&-; echo OK'
581 1.6 kre
582 1.6 kre # and that we can put tracing on an external file, leaving stderr alone
583 1.6 kre
584 1.6 kre atf_require_prog grep
585 1.6 kre
586 1.6 kre rm -f X-trace
587 1.6 kre atf_check -s exit:0 \
588 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
589 1.6 kre -e empty \
590 1.6 kre ${TEST_SH} -ec 'PS4=; set -X 2>X-trace; printf "%s" OK; echo OK'
591 1.6 kre test -s X-trace || atf_fail "T1: Failed to create trace output file"
592 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
593 1.6 kre atf_fail "T1: -X tracing missing printf"
594 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace ||
595 1.6 kre atf_fail "T1: -X tracing missing echo"
596 1.6 kre
597 1.6 kre rm -f X-trace
598 1.6 kre atf_check -s exit:0 \
599 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
600 1.6 kre -e empty \
601 1.6 kre ${TEST_SH} -ec \
602 1.6 kre 'PS4=; set -X 2>X-trace;
603 1.6 kre printf "%s" OK;
604 1.6 kre exec 2>/dev/null;
605 1.6 kre echo OK'
606 1.6 kre test -s X-trace || atf_fail "T2: Failed to create trace output file"
607 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
608 1.6 kre atf_fail "T2: -X tracing missing printf"
609 1.6 kre grep >/dev/null 2>&1 'exec' X-trace ||
610 1.6 kre atf_fail "T2: -X tracing missing exec"
611 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace ||
612 1.6 kre atf_fail "T2: -X tracing missing echo after stderr redirect"
613 1.6 kre
614 1.6 kre rm -f X-trace
615 1.6 kre atf_check -s exit:0 \
616 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
617 1.6 kre -e empty \
618 1.6 kre ${TEST_SH} -ec \
619 1.6 kre 'PS4=; set -X 2>X-trace;
620 1.6 kre printf "%s" OK;
621 1.6 kre set -X 2>/dev/null;
622 1.6 kre echo OK'
623 1.6 kre test -s X-trace || atf_fail "T3: Failed to create trace output file"
624 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
625 1.6 kre atf_fail "T3: -X tracing missing printf"
626 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
627 1.6 kre atf_fail "T3: -X tracing missing set -X"
628 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace &&
629 1.6 kre atf_fail "T3: -X tracing included echo after set -X redirect"
630 1.6 kre
631 1.6 kre rm -f X-trace
632 1.6 kre atf_check -s exit:0 \
633 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
634 1.6 kre -e match:echo -e match:OK -e not-match:printf \
635 1.6 kre ${TEST_SH} -ec \
636 1.6 kre 'PS4=; set -X 2>X-trace;
637 1.6 kre printf "%s" OK;
638 1.6 kre set -X;
639 1.6 kre echo OK'
640 1.6 kre test -s X-trace || atf_fail "T4: Failed to create trace output file"
641 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
642 1.6 kre atf_fail "T4: -X tracing missing printf"
643 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
644 1.6 kre atf_fail "T4: -X tracing missing set -X"
645 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace &&
646 1.6 kre atf_fail "T4: -X tracing included echo after set -X redirect"
647 1.6 kre
648 1.6 kre # Now check that -X and the tracing files work properly wrt functions
649 1.6 kre
650 1.6 kre # a shell that supports -X should support "local -" ... but verify
651 1.6 kre
652 1.6 kre ( ${TEST_SH} -c 'fn() { local - || exit 2; set -f; }; set +f; fn;
653 1.6 kre case "$-" in ("*f*") exit 1;; esac; exit 0' ) 2>/dev/null ||
654 1.6 kre atf_skip "-X function test: 'local -' unsupported"
655 1.6 kre
656 1.6 kre rm -f X-trace X-trace-fn
657 1.6 kre atf_check -s exit:0 \
658 1.6 kre -o match:OKhelloGOOD \
659 1.6 kre -e empty \
660 1.6 kre ${TEST_SH} -c '
661 1.6 kre say() {
662 1.6 kre printf "%s" "$*"
663 1.6 kre }
664 1.6 kre funct() {
665 1.6 kre local -
666 1.6 kre
667 1.6 kre set -X 2>X-trace-fn
668 1.6 kre say hello
669 1.6 kre }
670 1.6 kre
671 1.6 kre set -X 2>X-trace
672 1.6 kre
673 1.6 kre printf OK
674 1.6 kre funct
675 1.6 kre echo GOOD
676 1.6 kre '
677 1.6 kre test -s X-trace || atf_fail "T5: Failed to create trace output file"
678 1.6 kre test -s X-trace-fn || atf_fail "T5: Failed to create fn trace output"
679 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
680 1.6 kre atf_fail "T5: -X tracing missing printf"
681 1.6 kre grep >/dev/null 2>&1 funct X-trace ||
682 1.6 kre atf_fail "T5: -X tracing missing funct"
683 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
684 1.6 kre atf_fail "T5: -X tracing missing set -X from in funct"
685 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
686 1.6 kre atf_fail "T5: -X tracing missing echo after funct redirect"
687 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
688 1.6 kre atf_fail "T5: -X tracing included 'say' after funct redirect"
689 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace-fn ||
690 1.6 kre atf_fail "T5: -X funct tracing missed 'say'"
691 1.6 kre
692 1.6 kre rm -f X-trace X-trace-fn
693 1.6 kre
694 1.6 kre atf_check -s exit:0 \
695 1.6 kre -o match:OKhelloGOOD \
696 1.6 kre -e empty \
697 1.6 kre ${TEST_SH} -c '
698 1.6 kre say() {
699 1.6 kre printf "%s" "$*"
700 1.6 kre }
701 1.6 kre funct() {
702 1.6 kre local -
703 1.6 kre
704 1.6 kre set +X
705 1.6 kre say hello
706 1.6 kre }
707 1.6 kre
708 1.6 kre set -X 2>X-trace
709 1.6 kre
710 1.6 kre printf OK
711 1.6 kre funct
712 1.6 kre echo GOOD
713 1.6 kre '
714 1.6 kre test -s X-trace || atf_fail "T6: Failed to create trace output file"
715 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
716 1.6 kre atf_fail "T6: -X tracing missing printf"
717 1.6 kre grep >/dev/null 2>&1 funct X-trace ||
718 1.6 kre atf_fail "T6: -X tracing missing funct"
719 1.6 kre grep >/dev/null 2>&1 'set.*+X' X-trace ||
720 1.6 kre atf_fail "T6: -X tracing missing set +X from in funct"
721 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
722 1.6 kre atf_fail "T6: -X tracing missing echo after funct redirect"
723 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
724 1.6 kre atf_fail "T6: -X tracing included 'say' after funct redirect"
725 1.6 kre
726 1.6 kre rm -f X-trace
727 1.6 kre
728 1.6 kre atf_check -s exit:0 \
729 1.6 kre -o match:OKtracednotraceGOOD \
730 1.6 kre -e match:say -e match:traced -e not-match:notrace \
731 1.6 kre ${TEST_SH} -c '
732 1.6 kre say() {
733 1.6 kre printf "%s" "$*"
734 1.6 kre }
735 1.6 kre funct() {
736 1.6 kre local -
737 1.6 kre
738 1.6 kre set +X -x
739 1.6 kre
740 1.6 kre say traced
741 1.6 kre exec 2>/dev/null
742 1.6 kre say notrace
743 1.6 kre
744 1.6 kre }
745 1.6 kre
746 1.6 kre set -X 2>X-trace
747 1.6 kre
748 1.6 kre printf OK
749 1.6 kre funct
750 1.6 kre echo GOOD
751 1.6 kre '
752 1.6 kre test -s X-trace || atf_fail "T7: Failed to create trace output file"
753 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
754 1.6 kre atf_fail "T7: -X tracing missing printf"
755 1.6 kre grep >/dev/null 2>&1 funct X-trace ||
756 1.6 kre atf_fail "T7: -X tracing missing funct"
757 1.6 kre grep >/dev/null 2>&1 'set.*+X.*-x' X-trace ||
758 1.6 kre atf_fail "T7: -X tracing missing set +X -x from in funct"
759 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
760 1.6 kre atf_fail "T7: -X tracing missing echo after funct +X"
761 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
762 1.6 kre atf_fail "T7: -X tracing included 'say' after funct +X"
763 1.6 kre
764 1.6 kre rm -f X-trace X-trace-fn
765 1.6 kre atf_check -s exit:0 \
766 1.6 kre -o "match:OKg'daybye-bye.*hello.*GOOD" \
767 1.6 kre -e empty \
768 1.6 kre ${TEST_SH} -c '
769 1.6 kre say() {
770 1.6 kre printf "%s" "$*"
771 1.6 kre }
772 1.6 kre fn1() {
773 1.6 kre local -
774 1.6 kre
775 1.6 kre set -X 2>>X-trace-fn
776 1.6 kre say "g'\''day"
777 1.6 kre "$@"
778 1.6 kre say bye-bye
779 1.6 kre }
780 1.6 kre fn2() {
781 1.6 kre set +X
782 1.6 kre say hello
783 1.6 kre "$@"
784 1.6 kre say goodbye
785 1.6 kre }
786 1.6 kre
787 1.6 kre set -X 2>X-trace
788 1.6 kre
789 1.6 kre printf OK
790 1.6 kre fn1
791 1.6 kre fn1 fn2
792 1.6 kre fn1 fn1 fn2
793 1.6 kre fn1 fn2 fn1 fn2 fn1
794 1.6 kre fn1 fn1 fn2 fn2 fn1
795 1.6 kre echo GOOD
796 1.6 kre '
797 1.6 kre
798 1.6 kre # That test generally succeeds if the earlier ones did
799 1.6 kre # and if it did not dump core!
800 1.6 kre
801 1.6 kre # But we can check a few things...
802 1.6 kre
803 1.6 kre test -s X-trace || atf_fail "T8: Failed to create trace output file"
804 1.6 kre test -s X-trace-fn || atf_fail "T8: Failed to create trace output file"
805 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
806 1.6 kre atf_fail "T8: -X tracing missing printf"
807 1.6 kre grep >/dev/null 2>&1 fn1 X-trace ||
808 1.6 kre atf_fail "T8: -X tracing missing fn1"
809 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
810 1.6 kre atf_fail "T8: -X tracing missing set -X from in fn1"
811 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
812 1.6 kre atf_fail "T8: -X tracing missing echo after fn1 redirect"
813 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
814 1.6 kre atf_fail "T8: -X tracing included 'say' after fn2 +X"
815 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace-fn &&
816 1.6 kre atf_fail "T8: -X fn tracing included 'say' after fn2 +X"
817 1.6 kre
818 1.6 kre
819 1.6 kre rm -f X-trace
820 1.6 kre
821 1.6 kre return 0
822 1.6 kre }
823 1.6 kre
824 1.1 christos opt_test_setup()
825 1.1 christos {
826 1.1 christos test -n "$1" || { echo >&2 "Internal error"; exit 1; }
827 1.1 christos
828 1.1 christos cat > "$1" << 'END_OF_FUNCTIONS'
829 1.1 christos local_opt_check()
830 1.1 christos {
831 1.1 christos local -
832 1.1 christos }
833 1.1 christos
834 1.1 christos instr()
835 1.1 christos {
836 1.1 christos expr "$2" : "\(.*$1\)" >/dev/null
837 1.1 christos }
838 1.1 christos
839 1.1 christos save_opts()
840 1.1 christos {
841 1.1 christos local -
842 1.1 christos
843 1.1 christos set -e
844 1.1 christos set -u
845 1.1 christos
846 1.1 christos instr e "$-" && instr u "$-" && return 0
847 1.1 christos echo ERR
848 1.1 christos }
849 1.1 christos
850 1.1 christos fiddle_opts()
851 1.1 christos {
852 1.1 christos set -e
853 1.1 christos set -u
854 1.1 christos
855 1.1 christos instr e "$-" && instr u "$-" && return 0
856 1.1 christos echo ERR
857 1.1 christos }
858 1.1 christos
859 1.1 christos local_test()
860 1.1 christos {
861 1.1 christos set +eu
862 1.1 christos
863 1.1 christos save_opts
864 1.1 christos instr '[eu]' "$-" || printf %s "OK"
865 1.1 christos
866 1.1 christos fiddle_opts
867 1.1 christos instr e "$-" && instr u "$-" && printf %s "OK"
868 1.1 christos
869 1.1 christos set +eu
870 1.1 christos }
871 1.1 christos END_OF_FUNCTIONS
872 1.1 christos }
873 1.1 christos
874 1.1 christos atf_test_case restore_local_opts
875 1.1 christos restore_local_opts_head() {
876 1.1 christos atf_set "descr" "Tests that 'local -' saves and restores options. " \
877 1.1 christos "Note that "local" is a local shell addition"
878 1.1 christos }
879 1.1 christos restore_local_opts_body() {
880 1.1 christos atf_require_prog cat
881 1.1 christos atf_require_prog expr
882 1.1 christos
883 1.1 christos FN="test-funcs.$$"
884 1.1 christos opt_test_setup "${FN}" || atf_skip "Cannot setup test environment"
885 1.1 christos
886 1.2 christos ${TEST_SH} -ec ". './${FN}'; local_opt_check" 2>/dev/null ||
887 1.1 christos atf_skip "sh extension 'local -' not supported by ${TEST_SH}"
888 1.1 christos
889 1.1 christos atf_check -s exit:0 -o match:OKOK -o not-match:ERR -e empty \
890 1.2 christos ${TEST_SH} -ec ". './${FN}'; local_test"
891 1.1 christos }
892 1.1 christos
893 1.1 christos atf_test_case vi_emacs_VE_toggle
894 1.1 christos vi_emacs_VE_toggle_head() {
895 1.1 christos atf_set "descr" "Tests enabling vi disables emacs (and v.v - but why?)"\
896 1.1 christos " Note that -V and -E are local shell additions"
897 1.1 christos }
898 1.1 christos vi_emacs_VE_toggle_body() {
899 1.1 christos
900 1.1 christos test_optional_on_off V E ||
901 1.1 christos atf_skip "One or both V & E opts unsupported by ${TEST_SH}"
902 1.1 christos
903 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '
904 1.1 christos q() {
905 1.1 christos eval "case \"$-\" in
906 1.1 christos (*${2}*) return 1;;
907 1.1 christos (*${1}*) return 0;;
908 1.1 christos esac"
909 1.1 christos return 1
910 1.1 christos }
911 1.1 christos x() {
912 1.1 christos echo >&2 "Option set or toggle failure:" \
913 1.1 christos " on=$1 off=$2 set=$-"
914 1.1 christos exit 1
915 1.1 christos }
916 1.1 christos set -V; q V E || x V E
917 1.1 christos set -E; q E V || x E V
918 1.1 christos set -V; q V E || x V E
919 1.1 christos set +EV; q "" "[VE]" || x "" VE
920 1.1 christos exit 0
921 1.1 christos '
922 1.1 christos }
923 1.1 christos
924 1.5 kre atf_test_case pipefail
925 1.5 kre pipefail_head() {
926 1.5 kre atf_set "descr" "Basic tests of the pipefail option"
927 1.5 kre }
928 1.5 kre pipefail_body() {
929 1.5 kre ${TEST_SH} -c 'set -o pipefail' 2>/dev/null ||
930 1.5 kre atf_skip "pipefail option not supported by ${TEST_SH}"
931 1.5 kre
932 1.5 kre atf_check -s exit:0 -o match:'pipefail.*off' -e empty ${TEST_SH} -c \
933 1.5 kre 'set -o | grep pipefail'
934 1.5 kre atf_check -s exit:0 -o match:'pipefail.*on' -e empty ${TEST_SH} -c \
935 1.5 kre 'set -o pipefail; set -o | grep pipefail'
936 1.5 kre
937 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
938 1.5 kre '(exit 1) | (exit 2) | (exit 0)'
939 1.5 kre atf_check -s exit:2 -o empty -e empty ${TEST_SH} -c \
940 1.5 kre 'set -o pipefail; (exit 1) | (exit 2) | (exit 0)'
941 1.5 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
942 1.5 kre 'set -o pipefail; (exit 1) | (exit 0) | (exit 0)'
943 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
944 1.5 kre 'set -o pipefail; (exit 0) | (exit 0) | (exit 0)'
945 1.5 kre
946 1.5 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
947 1.5 kre '! (exit 1) | (exit 2) | (exit 0)'
948 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
949 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 2) | (exit 0)'
950 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
951 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 0) | (exit 0)'
952 1.5 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
953 1.5 kre 'set -o pipefail; ! (exit 0) | (exit 0) | (exit 0)'
954 1.5 kre
955 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
956 1.5 kre '(exit 1) | (exit 2) | (exit 0); echo $?'
957 1.5 kre atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
958 1.5 kre 'set -o pipefail; (exit 1) | (exit 2) | (exit 0); echo $?'
959 1.5 kre atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
960 1.5 kre 'set -o pipefail; (exit 1) | (exit 0) | (exit 0); echo $?'
961 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
962 1.5 kre 'set -o pipefail; (exit 0) | (exit 0) | (exit 0); echo $?'
963 1.5 kre
964 1.5 kre atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
965 1.5 kre '! (exit 1) | (exit 2) | (exit 0); echo $?'
966 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
967 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 2) | (exit 0); echo $?'
968 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
969 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 0) | (exit 0); echo $?'
970 1.5 kre atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
971 1.5 kre 'set -o pipefail; ! (exit 0) | (exit 0) | (exit 0); echo $?'
972 1.5 kre }
973 1.5 kre
974 1.1 christos atf_test_case xx_bogus
975 1.1 christos xx_bogus_head() {
976 1.1 christos atf_set "descr" "Tests that attempting to set a nonsense option fails."
977 1.1 christos }
978 1.1 christos xx_bogus_body() {
979 1.1 christos # Biggest problem here is picking a "nonsense option" that is
980 1.1 christos # not implemented by any shell, anywhere. Hopefully this will do.
981 1.3 christos
982 1.3 christos # 'set' is a special builtin, so a conforming shell should exit
983 1.3 christos # on an arg error, and the ERR should not be printed.
984 1.1 christos atf_check -s not-exit:0 -o empty -e not-empty \
985 1.2 christos ${TEST_SH} -c 'set -% ; echo ERR'
986 1.1 christos }
987 1.1 christos
988 1.1 christos atf_test_case Option_switching
989 1.1 christos Option_switching_head() {
990 1.1 christos atf_set "descr" "options can be enabled and disabled"
991 1.1 christos }
992 1.1 christos Option_switching_body() {
993 1.1 christos
994 1.1 christos # Cannot test -m, setting it causes test shell to fail...
995 1.1 christos # (test shell gets SIGKILL!) Wonder why ... something related to atf
996 1.1 christos # That is, it works if just run as "sh -c 'echo $-; set -m; echo $-'"
997 1.1 christos
998 1.1 christos # Don't bother testing toggling -n, once on, it stays on...
999 1.1 christos # (and because the test fn refuses to allow us to try)
1000 1.1 christos
1001 1.1 christos # Cannot test -o or -c here, or the extension -s
1002 1.1 christos # they can only be used, not switched
1003 1.1 christos
1004 1.1 christos # these are the posix options, that all shells should implement
1005 1.1 christos test_option_on_off a b C e f h u v x # m
1006 1.1 christos
1007 1.1 christos # and these are extensions that might not exist (non-fatal to test)
1008 1.1 christos # -i and -s (and -c) are posix options, but are not required to
1009 1.1 christos # be accessable via the "set" command, just the command line.
1010 1.1 christos # We allow for -i to work with set, as that makes some sense,
1011 1.1 christos # -c and -s do not.
1012 1.6 kre test_optional_on_off E i I p q V X || true
1013 1.1 christos
1014 1.1 christos # Also test (some) option combinations ...
1015 1.1 christos # only testing posix options here, because it is easier...
1016 1.1 christos test_option_on_off aeu vx Ca aCefux
1017 1.1 christos }
1018 1.1 christos
1019 1.1 christos atf_init_test_cases() {
1020 1.1 christos # tests are run in order sort of names produces, so choose names wisely
1021 1.1 christos
1022 1.1 christos # this one tests turning on/off all the mandatory. and extra flags
1023 1.1 christos atf_add_test_case Option_switching
1024 1.1 christos # and this tests the NetBSD "local -" functionality in functions.
1025 1.1 christos atf_add_test_case restore_local_opts
1026 1.1 christos
1027 1.1 christos # no tests for -m (no idea how to do that one)
1028 1.1 christos # -I (no easy way to generate the EOF it ignores)
1029 1.1 christos # -i (not sure how to test that one at the minute)
1030 1.2 christos # -p (because we aren't going to run tests setuid)
1031 1.1 christos # -V/-E (too much effort, and a real test would be huge)
1032 1.1 christos # -c (because almost all the other tests test it anyway)
1033 1.1 christos # -q (because, for now, I am lazy)
1034 1.1 christos # -s (coming soon, hopefully)
1035 1.1 christos # -o (really +o: again, hopefully soon)
1036 1.1 christos # -o longname (again, just laziness, don't wait...)
1037 1.1 christos # -h/-b (because NetBSD doesn't implement them)
1038 1.1 christos atf_add_test_case set_a
1039 1.1 christos atf_add_test_case set_C
1040 1.1 christos atf_add_test_case set_e
1041 1.1 christos atf_add_test_case set_f
1042 1.1 christos atf_add_test_case set_n
1043 1.1 christos atf_add_test_case set_u
1044 1.1 christos atf_add_test_case set_v
1045 1.1 christos atf_add_test_case set_x
1046 1.6 kre atf_add_test_case set_X
1047 1.1 christos
1048 1.1 christos atf_add_test_case vi_emacs_VE_toggle
1049 1.5 kre
1050 1.5 kre atf_add_test_case pipefail
1051 1.5 kre
1052 1.1 christos atf_add_test_case xx_bogus
1053 1.1 christos }
1054