t_option.sh revision 1.9 1 1.9 andvar # $NetBSD: t_option.sh,v 1.9 2022/05/22 11:27:36 andvar 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.7 msaitoh atf_set "descr" "Tests that 'set -n' suppresses 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.8 kre ${TEST_SH} ||
458 1.8 kre atf_fail '111 222 333 test failure'
459 1.1 christos }
460 1.1 christos
461 1.1 christos atf_test_case set_x
462 1.1 christos set_x_head() {
463 1.1 christos atf_set "descr" "Tests that 'set -x' turns on command exec logging " \
464 1.1 christos "and that it behaves as defined by the standard"
465 1.1 christos }
466 1.1 christos set_x_body() {
467 1.1 christos test_option_on_off x
468 1.1 christos
469 1.1 christos # check that cmd output appears after -x is enabled
470 1.1 christos atf_check -s exit:0 \
471 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
472 1.1 christos -e not-match:printf -e match:OK -e match:echo \
473 1.2 christos ${TEST_SH} -ec 'printf "%s" OK; set -x; echo OK; exit 0'
474 1.1 christos
475 1.1 christos # and that it stops again afer -x is disabled
476 1.1 christos atf_check -s exit:0 \
477 1.1 christos -o match:OKOK -o not-match:echo -o not-match:printf \
478 1.1 christos -e match:printf -e match:OK -e not-match:echo \
479 1.2 christos ${TEST_SH} -ec 'set -x; printf "%s" OK; set +x; echo OK; exit 0'
480 1.1 christos
481 1.1 christos # also check that PS4 is output correctly
482 1.1 christos atf_check -s exit:0 \
483 1.1 christos -o match:OK -o not-match:echo \
484 1.1 christos -e match:OK -e match:Run:echo \
485 1.2 christos ${TEST_SH} -ec 'PS4=Run:; set -x; echo OK; exit 0'
486 1.1 christos
487 1.1 christos return 0
488 1.1 christos
489 1.1 christos # This one seems controversial... I suspect it is NetBSD's sh
490 1.1 christos # that is wrong to not output "for" "while" "if" ... etc
491 1.1 christos
492 1.1 christos # and lastly, that shell keywords do not get output when "executed"
493 1.1 christos atf_check -s exit:0 \
494 1.1 christos -o match:111222333 -o not-match:printf \
495 1.1 christos -o not-match:for \
496 1.1 christos -e match:printf -e match:111 -e not-match:111222 \
497 1.1 christos -e not-match:for -e not-match:do -e not-match:done \
498 1.2 christos ${TEST_SH} -ec \
499 1.1 christos 'set -x; for i in 111 222 333; do printf "%s" $i; done; echo; exit 0'
500 1.1 christos }
501 1.1 christos
502 1.6 kre atf_test_case set_X
503 1.6 kre set_X_head() {
504 1.6 kre atf_set "descr" "Tests that 'set -X' turns on command exec logging " \
505 1.6 kre "and that it enables set -x and retains a single fd"
506 1.6 kre }
507 1.6 kre set_X_body() {
508 1.6 kre
509 1.6 kre # First we need to verify that $TEST_SH supports -X
510 1.6 kre test_optional_on_off X ||
511 1.6 kre atf_skip "$TEST_SH does not support -X"
512 1.6 kre
513 1.6 kre # and that the -X it implements is the -X we expect
514 1.6 kre $TEST_SH -c 'exec 2>/dev/null;
515 1.6 kre set +x; set -X;
516 1.6 kre case "$-" in (*x*) exit 0;; esac;
517 1.6 kre exit 1' ||
518 1.6 kre atf_skip "$TEST_SH supports -X but not 'the' -X"
519 1.6 kre
520 1.6 kre # Above has already tested that set -X => set -x
521 1.6 kre # Now test that set +X => set +x
522 1.6 kre # and that set -x and set +x do not affect -X
523 1.6 kre
524 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
525 1.6 kre 'set -x; set +X; case "$-" in (*x*) echo FAIL; exit 1;; esac'
526 1.6 kre
527 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
528 1.6 kre 'set -X; set +x;
529 1.6 kre case "$-" in (*x*) echo FAIL; exit 1;; esac
530 1.6 kre case "$-" in (*X*) exit 0;; esac; echo ERROR; exit 2'
531 1.6 kre
532 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
533 1.6 kre 'set -X; set +x; set -x;
534 1.6 kre case "$-" in (*x*X*|*X*x*) exit 0;; esac; echo ERROR; exit 2'
535 1.6 kre
536 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
537 1.6 kre 'set +X; set -x;
538 1.6 kre case "$-" in (*X*) echo FAIL; exit 1;; esac
539 1.6 kre case "$-" in (*x*) exit 0;; esac; echo ERROR; exit 2'
540 1.6 kre
541 1.6 kre atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \
542 1.6 kre 'set +X; set -x; set +x;
543 1.6 kre case "$-" in (*[xX]*) echo FAULT; exit 3;; esac'
544 1.6 kre
545 1.6 kre # The following just verify regular tracing using -X instead of -x
546 1.6 kre # These are the same tests as the -x test (set_x) performs.
547 1.6 kre
548 1.6 kre # check that cmd output appears after -X is enabled
549 1.6 kre atf_check -s exit:0 \
550 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
551 1.6 kre -e not-match:printf -e match:OK -e match:echo \
552 1.6 kre ${TEST_SH} -ec 'printf "%s" OK; set -X; echo OK; exit 0'
553 1.6 kre
554 1.6 kre # and that it stops again afer -X is disabled
555 1.6 kre atf_check -s exit:0 \
556 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
557 1.6 kre -e match:printf -e match:OK -e not-match:echo \
558 1.6 kre ${TEST_SH} -ec 'set -X; printf "%s" OK; set +X; echo OK; exit 0'
559 1.6 kre
560 1.6 kre # also check that PS4 is output correctly
561 1.6 kre atf_check -s exit:0 \
562 1.6 kre -o match:OK -o not-match:echo \
563 1.6 kre -e match:OK -e match:Run:echo \
564 1.6 kre ${TEST_SH} -ec 'PS4=Run:; set -X; echo OK; exit 0'
565 1.6 kre
566 1.6 kre # end copies of -x tests ...
567 1.6 kre
568 1.6 kre # now check that we can move stderr around without affecting -X output
569 1.6 kre
570 1.6 kre atf_check -s exit:0 \
571 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
572 1.6 kre -e match:printf -e match:OK -e match:echo \
573 1.6 kre ${TEST_SH} -ecX 'printf "%s" OK; exec 2>/dev/null; echo OK'
574 1.6 kre atf_check -s exit:0 \
575 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
576 1.6 kre -e match:printf -e match:OK -e match:echo \
577 1.6 kre ${TEST_SH} -ecX 'printf "%s" OK; exec 2>&1; echo OK'
578 1.6 kre atf_check -s exit:0 \
579 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
580 1.6 kre -e match:printf -e match:OK -e match:echo \
581 1.6 kre ${TEST_SH} -ecX 'printf "%s" OK; exec 2>&-; echo OK'
582 1.6 kre
583 1.6 kre # and that we can put tracing on an external file, leaving stderr alone
584 1.6 kre
585 1.6 kre atf_require_prog grep
586 1.6 kre
587 1.6 kre rm -f X-trace
588 1.6 kre atf_check -s exit:0 \
589 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
590 1.6 kre -e empty \
591 1.6 kre ${TEST_SH} -ec 'PS4=; set -X 2>X-trace; printf "%s" OK; echo OK'
592 1.6 kre test -s X-trace || atf_fail "T1: Failed to create trace output file"
593 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
594 1.6 kre atf_fail "T1: -X tracing missing printf"
595 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace ||
596 1.6 kre atf_fail "T1: -X tracing missing echo"
597 1.6 kre
598 1.6 kre rm -f X-trace
599 1.6 kre atf_check -s exit:0 \
600 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
601 1.6 kre -e empty \
602 1.6 kre ${TEST_SH} -ec \
603 1.6 kre 'PS4=; set -X 2>X-trace;
604 1.6 kre printf "%s" OK;
605 1.6 kre exec 2>/dev/null;
606 1.6 kre echo OK'
607 1.6 kre test -s X-trace || atf_fail "T2: Failed to create trace output file"
608 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
609 1.6 kre atf_fail "T2: -X tracing missing printf"
610 1.6 kre grep >/dev/null 2>&1 'exec' X-trace ||
611 1.6 kre atf_fail "T2: -X tracing missing exec"
612 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace ||
613 1.6 kre atf_fail "T2: -X tracing missing echo after stderr redirect"
614 1.6 kre
615 1.6 kre rm -f X-trace
616 1.6 kre atf_check -s exit:0 \
617 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
618 1.6 kre -e empty \
619 1.6 kre ${TEST_SH} -ec \
620 1.6 kre 'PS4=; set -X 2>X-trace;
621 1.6 kre printf "%s" OK;
622 1.6 kre set -X 2>/dev/null;
623 1.6 kre echo OK'
624 1.6 kre test -s X-trace || atf_fail "T3: Failed to create trace output file"
625 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
626 1.6 kre atf_fail "T3: -X tracing missing printf"
627 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
628 1.6 kre atf_fail "T3: -X tracing missing set -X"
629 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace &&
630 1.6 kre atf_fail "T3: -X tracing included echo after set -X redirect"
631 1.6 kre
632 1.6 kre rm -f X-trace
633 1.6 kre atf_check -s exit:0 \
634 1.6 kre -o match:OKOK -o not-match:echo -o not-match:printf \
635 1.6 kre -e match:echo -e match:OK -e not-match:printf \
636 1.6 kre ${TEST_SH} -ec \
637 1.6 kre 'PS4=; set -X 2>X-trace;
638 1.6 kre printf "%s" OK;
639 1.6 kre set -X;
640 1.6 kre echo OK'
641 1.6 kre test -s X-trace || atf_fail "T4: Failed to create trace output file"
642 1.6 kre grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace ||
643 1.6 kre atf_fail "T4: -X tracing missing printf"
644 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
645 1.6 kre atf_fail "T4: -X tracing missing set -X"
646 1.6 kre grep >/dev/null 2>&1 'echo.*OK' X-trace &&
647 1.6 kre atf_fail "T4: -X tracing included echo after set -X redirect"
648 1.6 kre
649 1.6 kre # Now check that -X and the tracing files work properly wrt functions
650 1.6 kre
651 1.6 kre # a shell that supports -X should support "local -" ... but verify
652 1.6 kre
653 1.6 kre ( ${TEST_SH} -c 'fn() { local - || exit 2; set -f; }; set +f; fn;
654 1.6 kre case "$-" in ("*f*") exit 1;; esac; exit 0' ) 2>/dev/null ||
655 1.6 kre atf_skip "-X function test: 'local -' unsupported"
656 1.6 kre
657 1.6 kre rm -f X-trace X-trace-fn
658 1.6 kre atf_check -s exit:0 \
659 1.6 kre -o match:OKhelloGOOD \
660 1.6 kre -e empty \
661 1.6 kre ${TEST_SH} -c '
662 1.6 kre say() {
663 1.6 kre printf "%s" "$*"
664 1.6 kre }
665 1.6 kre funct() {
666 1.6 kre local -
667 1.6 kre
668 1.6 kre set -X 2>X-trace-fn
669 1.6 kre say hello
670 1.6 kre }
671 1.6 kre
672 1.6 kre set -X 2>X-trace
673 1.6 kre
674 1.6 kre printf OK
675 1.6 kre funct
676 1.6 kre echo GOOD
677 1.6 kre '
678 1.6 kre test -s X-trace || atf_fail "T5: Failed to create trace output file"
679 1.6 kre test -s X-trace-fn || atf_fail "T5: Failed to create fn trace output"
680 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
681 1.6 kre atf_fail "T5: -X tracing missing printf"
682 1.6 kre grep >/dev/null 2>&1 funct X-trace ||
683 1.6 kre atf_fail "T5: -X tracing missing funct"
684 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
685 1.6 kre atf_fail "T5: -X tracing missing set -X from in funct"
686 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
687 1.6 kre atf_fail "T5: -X tracing missing echo after funct redirect"
688 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
689 1.6 kre atf_fail "T5: -X tracing included 'say' after funct redirect"
690 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace-fn ||
691 1.6 kre atf_fail "T5: -X funct tracing missed 'say'"
692 1.6 kre
693 1.6 kre rm -f X-trace X-trace-fn
694 1.6 kre
695 1.6 kre atf_check -s exit:0 \
696 1.6 kre -o match:OKhelloGOOD \
697 1.6 kre -e empty \
698 1.6 kre ${TEST_SH} -c '
699 1.6 kre say() {
700 1.6 kre printf "%s" "$*"
701 1.6 kre }
702 1.6 kre funct() {
703 1.6 kre local -
704 1.6 kre
705 1.6 kre set +X
706 1.6 kre say hello
707 1.6 kre }
708 1.6 kre
709 1.6 kre set -X 2>X-trace
710 1.6 kre
711 1.6 kre printf OK
712 1.6 kre funct
713 1.6 kre echo GOOD
714 1.6 kre '
715 1.6 kre test -s X-trace || atf_fail "T6: Failed to create trace output file"
716 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
717 1.6 kre atf_fail "T6: -X tracing missing printf"
718 1.6 kre grep >/dev/null 2>&1 funct X-trace ||
719 1.6 kre atf_fail "T6: -X tracing missing funct"
720 1.6 kre grep >/dev/null 2>&1 'set.*+X' X-trace ||
721 1.6 kre atf_fail "T6: -X tracing missing set +X from in funct"
722 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
723 1.6 kre atf_fail "T6: -X tracing missing echo after funct redirect"
724 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
725 1.6 kre atf_fail "T6: -X tracing included 'say' after funct redirect"
726 1.6 kre
727 1.6 kre rm -f X-trace
728 1.6 kre
729 1.6 kre atf_check -s exit:0 \
730 1.6 kre -o match:OKtracednotraceGOOD \
731 1.6 kre -e match:say -e match:traced -e not-match:notrace \
732 1.6 kre ${TEST_SH} -c '
733 1.6 kre say() {
734 1.6 kre printf "%s" "$*"
735 1.6 kre }
736 1.6 kre funct() {
737 1.6 kre local -
738 1.6 kre
739 1.6 kre set +X -x
740 1.6 kre
741 1.6 kre say traced
742 1.6 kre exec 2>/dev/null
743 1.6 kre say notrace
744 1.6 kre
745 1.6 kre }
746 1.6 kre
747 1.6 kre set -X 2>X-trace
748 1.6 kre
749 1.6 kre printf OK
750 1.6 kre funct
751 1.6 kre echo GOOD
752 1.6 kre '
753 1.6 kre test -s X-trace || atf_fail "T7: Failed to create trace output file"
754 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
755 1.6 kre atf_fail "T7: -X tracing missing printf"
756 1.6 kre grep >/dev/null 2>&1 funct X-trace ||
757 1.6 kre atf_fail "T7: -X tracing missing funct"
758 1.6 kre grep >/dev/null 2>&1 'set.*+X.*-x' X-trace ||
759 1.6 kre atf_fail "T7: -X tracing missing set +X -x from in funct"
760 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
761 1.6 kre atf_fail "T7: -X tracing missing echo after funct +X"
762 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
763 1.6 kre atf_fail "T7: -X tracing included 'say' after funct +X"
764 1.6 kre
765 1.6 kre rm -f X-trace X-trace-fn
766 1.6 kre atf_check -s exit:0 \
767 1.6 kre -o "match:OKg'daybye-bye.*hello.*GOOD" \
768 1.6 kre -e empty \
769 1.6 kre ${TEST_SH} -c '
770 1.6 kre say() {
771 1.6 kre printf "%s" "$*"
772 1.6 kre }
773 1.6 kre fn1() {
774 1.6 kre local -
775 1.6 kre
776 1.6 kre set -X 2>>X-trace-fn
777 1.6 kre say "g'\''day"
778 1.6 kre "$@"
779 1.6 kre say bye-bye
780 1.6 kre }
781 1.6 kre fn2() {
782 1.6 kre set +X
783 1.6 kre say hello
784 1.6 kre "$@"
785 1.6 kre say goodbye
786 1.6 kre }
787 1.6 kre
788 1.6 kre set -X 2>X-trace
789 1.6 kre
790 1.6 kre printf OK
791 1.6 kre fn1
792 1.6 kre fn1 fn2
793 1.6 kre fn1 fn1 fn2
794 1.6 kre fn1 fn2 fn1 fn2 fn1
795 1.6 kre fn1 fn1 fn2 fn2 fn1
796 1.6 kre echo GOOD
797 1.6 kre '
798 1.6 kre
799 1.6 kre # That test generally succeeds if the earlier ones did
800 1.6 kre # and if it did not dump core!
801 1.6 kre
802 1.6 kre # But we can check a few things...
803 1.6 kre
804 1.6 kre test -s X-trace || atf_fail "T8: Failed to create trace output file"
805 1.6 kre test -s X-trace-fn || atf_fail "T8: Failed to create trace output file"
806 1.6 kre grep >/dev/null 2>&1 'printf.*OK' X-trace ||
807 1.6 kre atf_fail "T8: -X tracing missing printf"
808 1.6 kre grep >/dev/null 2>&1 fn1 X-trace ||
809 1.6 kre atf_fail "T8: -X tracing missing fn1"
810 1.6 kre grep >/dev/null 2>&1 'set.*-X' X-trace ||
811 1.6 kre atf_fail "T8: -X tracing missing set -X from in fn1"
812 1.6 kre grep >/dev/null 2>&1 'echo.*GOOD' X-trace ||
813 1.6 kre atf_fail "T8: -X tracing missing echo after fn1 redirect"
814 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace &&
815 1.6 kre atf_fail "T8: -X tracing included 'say' after fn2 +X"
816 1.6 kre grep >/dev/null 2>&1 'say.*hello' X-trace-fn &&
817 1.6 kre atf_fail "T8: -X fn tracing included 'say' after fn2 +X"
818 1.6 kre
819 1.6 kre
820 1.6 kre rm -f X-trace
821 1.6 kre
822 1.6 kre return 0
823 1.6 kre }
824 1.6 kre
825 1.1 christos opt_test_setup()
826 1.1 christos {
827 1.1 christos test -n "$1" || { echo >&2 "Internal error"; exit 1; }
828 1.1 christos
829 1.1 christos cat > "$1" << 'END_OF_FUNCTIONS'
830 1.1 christos local_opt_check()
831 1.1 christos {
832 1.1 christos local -
833 1.1 christos }
834 1.1 christos
835 1.1 christos instr()
836 1.1 christos {
837 1.1 christos expr "$2" : "\(.*$1\)" >/dev/null
838 1.1 christos }
839 1.1 christos
840 1.1 christos save_opts()
841 1.1 christos {
842 1.1 christos local -
843 1.1 christos
844 1.1 christos set -e
845 1.1 christos set -u
846 1.1 christos
847 1.1 christos instr e "$-" && instr u "$-" && return 0
848 1.1 christos echo ERR
849 1.1 christos }
850 1.1 christos
851 1.1 christos fiddle_opts()
852 1.1 christos {
853 1.1 christos set -e
854 1.1 christos set -u
855 1.1 christos
856 1.1 christos instr e "$-" && instr u "$-" && return 0
857 1.1 christos echo ERR
858 1.1 christos }
859 1.1 christos
860 1.1 christos local_test()
861 1.1 christos {
862 1.1 christos set +eu
863 1.1 christos
864 1.1 christos save_opts
865 1.1 christos instr '[eu]' "$-" || printf %s "OK"
866 1.1 christos
867 1.1 christos fiddle_opts
868 1.1 christos instr e "$-" && instr u "$-" && printf %s "OK"
869 1.1 christos
870 1.1 christos set +eu
871 1.1 christos }
872 1.1 christos END_OF_FUNCTIONS
873 1.1 christos }
874 1.1 christos
875 1.1 christos atf_test_case restore_local_opts
876 1.1 christos restore_local_opts_head() {
877 1.1 christos atf_set "descr" "Tests that 'local -' saves and restores options. " \
878 1.1 christos "Note that "local" is a local shell addition"
879 1.1 christos }
880 1.1 christos restore_local_opts_body() {
881 1.1 christos atf_require_prog cat
882 1.1 christos atf_require_prog expr
883 1.1 christos
884 1.1 christos FN="test-funcs.$$"
885 1.1 christos opt_test_setup "${FN}" || atf_skip "Cannot setup test environment"
886 1.1 christos
887 1.2 christos ${TEST_SH} -ec ". './${FN}'; local_opt_check" 2>/dev/null ||
888 1.1 christos atf_skip "sh extension 'local -' not supported by ${TEST_SH}"
889 1.1 christos
890 1.1 christos atf_check -s exit:0 -o match:OKOK -o not-match:ERR -e empty \
891 1.2 christos ${TEST_SH} -ec ". './${FN}'; local_test"
892 1.1 christos }
893 1.1 christos
894 1.1 christos atf_test_case vi_emacs_VE_toggle
895 1.1 christos vi_emacs_VE_toggle_head() {
896 1.1 christos atf_set "descr" "Tests enabling vi disables emacs (and v.v - but why?)"\
897 1.1 christos " Note that -V and -E are local shell additions"
898 1.1 christos }
899 1.1 christos vi_emacs_VE_toggle_body() {
900 1.1 christos
901 1.1 christos test_optional_on_off V E ||
902 1.1 christos atf_skip "One or both V & E opts unsupported by ${TEST_SH}"
903 1.1 christos
904 1.2 christos atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '
905 1.1 christos q() {
906 1.1 christos eval "case \"$-\" in
907 1.1 christos (*${2}*) return 1;;
908 1.1 christos (*${1}*) return 0;;
909 1.1 christos esac"
910 1.1 christos return 1
911 1.1 christos }
912 1.1 christos x() {
913 1.1 christos echo >&2 "Option set or toggle failure:" \
914 1.1 christos " on=$1 off=$2 set=$-"
915 1.1 christos exit 1
916 1.1 christos }
917 1.1 christos set -V; q V E || x V E
918 1.1 christos set -E; q E V || x E V
919 1.1 christos set -V; q V E || x V E
920 1.1 christos set +EV; q "" "[VE]" || x "" VE
921 1.1 christos exit 0
922 1.1 christos '
923 1.1 christos }
924 1.1 christos
925 1.5 kre atf_test_case pipefail
926 1.5 kre pipefail_head() {
927 1.5 kre atf_set "descr" "Basic tests of the pipefail option"
928 1.5 kre }
929 1.5 kre pipefail_body() {
930 1.5 kre ${TEST_SH} -c 'set -o pipefail' 2>/dev/null ||
931 1.5 kre atf_skip "pipefail option not supported by ${TEST_SH}"
932 1.5 kre
933 1.5 kre atf_check -s exit:0 -o match:'pipefail.*off' -e empty ${TEST_SH} -c \
934 1.5 kre 'set -o | grep pipefail'
935 1.5 kre atf_check -s exit:0 -o match:'pipefail.*on' -e empty ${TEST_SH} -c \
936 1.5 kre 'set -o pipefail; set -o | grep pipefail'
937 1.5 kre
938 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
939 1.5 kre '(exit 1) | (exit 2) | (exit 0)'
940 1.5 kre atf_check -s exit:2 -o empty -e empty ${TEST_SH} -c \
941 1.5 kre 'set -o pipefail; (exit 1) | (exit 2) | (exit 0)'
942 1.5 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
943 1.5 kre 'set -o pipefail; (exit 1) | (exit 0) | (exit 0)'
944 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
945 1.5 kre 'set -o pipefail; (exit 0) | (exit 0) | (exit 0)'
946 1.5 kre
947 1.5 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
948 1.5 kre '! (exit 1) | (exit 2) | (exit 0)'
949 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
950 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 2) | (exit 0)'
951 1.5 kre atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
952 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 0) | (exit 0)'
953 1.5 kre atf_check -s exit:1 -o empty -e empty ${TEST_SH} -c \
954 1.5 kre 'set -o pipefail; ! (exit 0) | (exit 0) | (exit 0)'
955 1.5 kre
956 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
957 1.5 kre '(exit 1) | (exit 2) | (exit 0); echo $?'
958 1.5 kre atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
959 1.5 kre 'set -o pipefail; (exit 1) | (exit 2) | (exit 0); echo $?'
960 1.5 kre atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
961 1.5 kre 'set -o pipefail; (exit 1) | (exit 0) | (exit 0); echo $?'
962 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
963 1.5 kre 'set -o pipefail; (exit 0) | (exit 0) | (exit 0); echo $?'
964 1.5 kre
965 1.5 kre atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
966 1.5 kre '! (exit 1) | (exit 2) | (exit 0); echo $?'
967 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
968 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 2) | (exit 0); echo $?'
969 1.5 kre atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
970 1.5 kre 'set -o pipefail; ! (exit 1) | (exit 0) | (exit 0); echo $?'
971 1.5 kre atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
972 1.5 kre 'set -o pipefail; ! (exit 0) | (exit 0) | (exit 0); echo $?'
973 1.5 kre }
974 1.5 kre
975 1.1 christos atf_test_case xx_bogus
976 1.1 christos xx_bogus_head() {
977 1.1 christos atf_set "descr" "Tests that attempting to set a nonsense option fails."
978 1.1 christos }
979 1.1 christos xx_bogus_body() {
980 1.1 christos # Biggest problem here is picking a "nonsense option" that is
981 1.1 christos # not implemented by any shell, anywhere. Hopefully this will do.
982 1.3 christos
983 1.3 christos # 'set' is a special builtin, so a conforming shell should exit
984 1.3 christos # on an arg error, and the ERR should not be printed.
985 1.1 christos atf_check -s not-exit:0 -o empty -e not-empty \
986 1.2 christos ${TEST_SH} -c 'set -% ; echo ERR'
987 1.1 christos }
988 1.1 christos
989 1.1 christos atf_test_case Option_switching
990 1.1 christos Option_switching_head() {
991 1.1 christos atf_set "descr" "options can be enabled and disabled"
992 1.1 christos }
993 1.1 christos Option_switching_body() {
994 1.1 christos
995 1.1 christos # Cannot test -m, setting it causes test shell to fail...
996 1.1 christos # (test shell gets SIGKILL!) Wonder why ... something related to atf
997 1.1 christos # That is, it works if just run as "sh -c 'echo $-; set -m; echo $-'"
998 1.1 christos
999 1.1 christos # Don't bother testing toggling -n, once on, it stays on...
1000 1.1 christos # (and because the test fn refuses to allow us to try)
1001 1.1 christos
1002 1.1 christos # Cannot test -o or -c here, or the extension -s
1003 1.1 christos # they can only be used, not switched
1004 1.1 christos
1005 1.1 christos # these are the posix options, that all shells should implement
1006 1.1 christos test_option_on_off a b C e f h u v x # m
1007 1.1 christos
1008 1.1 christos # and these are extensions that might not exist (non-fatal to test)
1009 1.1 christos # -i and -s (and -c) are posix options, but are not required to
1010 1.9 andvar # be accessible via the "set" command, just the command line.
1011 1.1 christos # We allow for -i to work with set, as that makes some sense,
1012 1.1 christos # -c and -s do not.
1013 1.6 kre test_optional_on_off E i I p q V X || true
1014 1.1 christos
1015 1.1 christos # Also test (some) option combinations ...
1016 1.1 christos # only testing posix options here, because it is easier...
1017 1.1 christos test_option_on_off aeu vx Ca aCefux
1018 1.1 christos }
1019 1.1 christos
1020 1.1 christos atf_init_test_cases() {
1021 1.1 christos # tests are run in order sort of names produces, so choose names wisely
1022 1.1 christos
1023 1.1 christos # this one tests turning on/off all the mandatory. and extra flags
1024 1.1 christos atf_add_test_case Option_switching
1025 1.1 christos # and this tests the NetBSD "local -" functionality in functions.
1026 1.1 christos atf_add_test_case restore_local_opts
1027 1.1 christos
1028 1.1 christos # no tests for -m (no idea how to do that one)
1029 1.1 christos # -I (no easy way to generate the EOF it ignores)
1030 1.1 christos # -i (not sure how to test that one at the minute)
1031 1.2 christos # -p (because we aren't going to run tests setuid)
1032 1.1 christos # -V/-E (too much effort, and a real test would be huge)
1033 1.1 christos # -c (because almost all the other tests test it anyway)
1034 1.1 christos # -q (because, for now, I am lazy)
1035 1.1 christos # -s (coming soon, hopefully)
1036 1.1 christos # -o (really +o: again, hopefully soon)
1037 1.1 christos # -o longname (again, just laziness, don't wait...)
1038 1.1 christos # -h/-b (because NetBSD doesn't implement them)
1039 1.1 christos atf_add_test_case set_a
1040 1.1 christos atf_add_test_case set_C
1041 1.1 christos atf_add_test_case set_e
1042 1.1 christos atf_add_test_case set_f
1043 1.1 christos atf_add_test_case set_n
1044 1.1 christos atf_add_test_case set_u
1045 1.1 christos atf_add_test_case set_v
1046 1.1 christos atf_add_test_case set_x
1047 1.6 kre atf_add_test_case set_X
1048 1.1 christos
1049 1.1 christos atf_add_test_case vi_emacs_VE_toggle
1050 1.5 kre
1051 1.5 kre atf_add_test_case pipefail
1052 1.5 kre
1053 1.1 christos atf_add_test_case xx_bogus
1054 1.1 christos }
1055