1 # $NetBSD: t_set_e.sh,v 1.5 2008/05/25 21:43:18 dholland Exp $
3 # Copyright (c) 2007 The NetBSD Foundation, Inc.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
29 # http://www.opengroup.org/onlinepubs/009695399/utilities/set.html
30 # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
32 # the implementation of "sh" to test
38 "") SH_FAILS
=`echo "$1"`;;
39 *) SH_FAILS
="$SH_FAILS"`echo; echo "$1"`;;
45 #echo "$TEST_SH -c $1"
46 result
=`$TEST_SH -c "$1" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//'`
47 if [ "$result" != "$2" ]; then
48 MSG
=`printf "%-56s %-8s %s" "$3" "$result" "$2"`
50 failcount
=`expr $failcount + 1`
52 count
=`expr $count + 1`
55 # direct check: try the given expression.
61 # eval check: indirect through eval.
62 # as of this writing, this changes the behavior pretty drastically and
63 # is thus important to test. (PR bin/29861)
66 check1
'eval '"'($1)'" "$2" "eval '($1)'"
71 atf_set
"descr" "Tests that 'set -e' works correctly"
77 # make sure exiting from a subshell behaves as expected
78 dcheck
'(set -e; exit 1; echo ERR$?); echo OK$?' 'OK1'
79 echeck
'(set -e; exit 1; echo ERR$?); echo OK$?' 'OK1'
81 # first, check basic functioning.
82 # The ERR shouldn't print; the result of the () should be 1.
83 # Henceforth we'll assume that we don't need to check $?.
84 dcheck
'(set -e; false; echo ERR$?); echo -n OK$?' 'OK1'
85 echeck
'(set -e; false; echo ERR$?); echo -n OK$?' 'OK1'
87 # these cases should be equivalent to the preceding.
88 dcheck
'(set -e; /nonexistent; echo ERR); echo OK' 'OK'
89 echeck
'(set -e; /nonexistent; echo ERR); echo OK' 'OK'
90 dcheck
'(set -e; nonexistent-program-on-path; echo ERR); echo OK' 'OK'
91 echeck
'(set -e; nonexistent-program-on-path; echo ERR); echo OK' 'OK'
92 dcheck
'f() { false; }; (set -e; f; echo ERR); echo OK' 'OK'
93 echeck
'f() { false; }; (set -e; f; echo ERR); echo OK' 'OK'
94 dcheck
'f() { return 1; }; (set -e; f; echo ERR); echo OK' 'OK'
95 echeck
'f() { return 1; }; (set -e; f; echo ERR); echo OK' 'OK'
97 # but! with set -e, the false should cause an *immediate* exit.
98 # The return form should not, as such, but there's no way to
100 dcheck
'f() { false; echo ERR; }; (set -e; f); echo OK' 'OK'
101 echeck
'f() { false; echo ERR; }; (set -e; f); echo OK' 'OK'
103 # set is not scoped, so these should not exit at all.
104 dcheck
'f() { set +e; false; echo OK; }; (set -e; f); echo OK' 'OK OK'
105 echeck
'f() { set +e; false; echo OK; }; (set -e; f); echo OK' 'OK OK'
107 # according to the standard, only failing *simple* commands
108 # cause an exit under -e. () is not a simple command.
109 dcheck
'(set -e; (set +e; false; echo OK; false); echo OK)' 'OK OK'
110 echeck
'(set -e; (set +e; false; echo OK; false); echo OK)' 'OK OK'
112 # make sure an inner nested shell does exit though.
113 dcheck
'(set -e; (false; echo ERR)); echo OK' 'OK'
115 # The left hand side of an || or && is explicitly tested and
116 # thus should not cause an exit. Furthermore, because a || or
117 # && expression is not a simple command, there should be no
118 # exit even if the overall result is false.
119 dcheck
'(set -e; false || true; echo OK); echo OK' 'OK OK'
120 echeck
'(set -e; false || true; echo OK); echo OK' 'OK OK'
121 dcheck
'(set -e; false && true; echo OK); echo OK' 'OK OK'
122 echeck
'(set -e; false && true; echo OK); echo OK' 'OK OK'
124 # However, the right hand side is not tested, so a failure
125 # there *should* cause an exit, regardless of whether it
126 # appears inside a non-simple command.
128 # Note that in at least one place the standard does not
129 # distinguish between the left and right hand sides of
130 # logical operators. It is possible that for strict
131 # compliance these need to not exit; however, if so that
132 # should probably be limited to when some strict-posix setting
133 # is in effect and tested accordingly.
135 dcheck
'(set -e; false || false; echo ERR); echo OK' 'OK'
136 dcheck
'(set -e; false && false; echo ERR); echo OK' 'OK'
137 dcheck
'(set -e; true && false; echo ERR); echo OK' 'OK'
138 echeck
'(set -e; false || false; echo ERR); echo OK' 'OK'
139 echeck
'(set -e; false && false; echo ERR); echo OK' 'OK'
140 echeck
'(set -e; true && false; echo ERR); echo OK' 'OK'
142 # A failure that is not reached because of short-circuit
143 # evaluation should not cause an exit, however.
144 dcheck
'(set -e; true || false; echo OK); echo OK' 'OK OK'
145 echeck
'(set -e; true || false; echo OK); echo OK' 'OK OK'
147 # For completeness, test the other two combinations.
148 dcheck
'(set -e; true || true; echo OK); echo OK' 'OK OK'
149 dcheck
'(set -e; true && true; echo OK); echo OK' 'OK OK'
150 echeck
'(set -e; true || true; echo OK); echo OK' 'OK OK'
151 echeck
'(set -e; true && true; echo OK); echo OK' 'OK OK'
153 # likewise, none of these should exit.
154 dcheck
'(set -e; while false; do :; done; echo OK); echo OK' 'OK OK'
155 dcheck
'(set -e; if false; then :; fi; echo OK); echo OK' 'OK OK'
157 #dcheck '(set -e; until false; do :; done; echo OK); echo OK' 'OK OK'
158 dcheck
'(set -e; until [ "$t" = 1 ]; do t=1; done; echo OK); echo OK' \
160 echeck
'(set -e; while false; do :; done; echo OK); echo OK' 'OK OK'
161 echeck
'(set -e; if false; then :; fi; echo OK); echo OK' 'OK OK'
162 echeck
'(set -e; until [ "$t" = 1 ]; do t=1; done; echo OK); echo OK' \
165 # the bang operator tests its argument and thus the argument
166 # should not cause an exit. it is also not a simple command (I
167 # believe) so it also shouldn't exit even if it yields a false
169 dcheck
'(set -e; ! false; echo OK); echo OK' 'OK OK'
170 dcheck
'(set -e; ! true; echo OK); echo OK' 'OK OK'
171 echeck
'(set -e; ! false; echo OK); echo OK' 'OK OK'
172 echeck
'(set -e; ! true; echo OK); echo OK' 'OK OK'
174 # combined case with () and &&; the inner expression is false
175 # but does not itself exit, and the () should not cause an
176 # exit even when failing.
177 dcheck
'(set -e; (false && true); echo OK); echo OK' 'OK OK'
178 echeck
'(set -e; (false && true); echo OK); echo OK' 'OK OK'
180 # pipelines. only the right-hand end is significant.
181 dcheck
'(set -e; false | true; echo OK); echo OK' 'OK OK'
182 echeck
'(set -e; false | true; echo OK); echo OK' 'OK OK'
183 dcheck
'(set -e; true | false; echo ERR); echo OK' 'OK'
184 echeck
'(set -e; true | false; echo ERR); echo OK' 'OK'
186 dcheck
'(set -e; while true | false; do :; done; echo OK); echo OK' \
188 dcheck
'(set -e; if true | false; then :; fi; echo OK); echo OK' \
192 # According to dsl@ in PR bin/32282, () is not defined as a
193 # subshell, only as a grouping operator [and a scope, I guess]
194 # so the nested false ought to cause the whole shell to exit,
195 # not just the subshell. dholland@ would like to see C&V,
196 # because that seems like a bad idea. (Among other things, it
197 # would break all the above test logic, which relies on being
198 # able to isolate set -e behavior inside ().) However, I'm
199 # going to put these tests here to make sure the issue gets
200 # dealt with sometime.
202 # 1. error if the whole shell exits (current behavior)
203 dcheck
'echo OK; (set -e; false); echo OK' 'OK OK'
204 echeck
'echo OK; (set -e; false); echo OK' 'OK OK'
205 # 2. error if the whole shell does not exit (dsl's suggested behavior)
206 dcheck
'echo OK; (set -e; false); echo ERR' 'OK'
207 echeck
'echo OK; (set -e; false); echo ERR' 'OK'
209 # The current behavior of the shell is that it exits out as
210 # far as -e is set and then stops. This is probably a
211 # consequence of it handling () wrong, but it's a somewhat
212 # curious compromise position between 1. and 2. above.
213 dcheck
'(set -e; (false; echo ERR); echo ERR); echo OK' 'OK'
214 echeck
'(set -e; (false; echo ERR); echo ERR); echo OK' 'OK'
216 # backquote expansion (PR bin/17514)
217 dcheck
'(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
218 dcheck
'(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
219 dcheck
'(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
220 dcheck
'(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
221 dcheck
'(set -e; x=`false`; echo ERR); echo OK' 'OK'
222 dcheck
'(set -e; x=$(false); echo ERR); echo OK' 'OK'
223 dcheck
'(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
224 dcheck
'(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
225 echeck
'(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
226 echeck
'(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
227 echeck
'(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
228 echeck
'(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
229 echeck
'(set -e; x=`false`; echo ERR); echo OK' 'OK'
230 echeck
'(set -e; x=$(false); echo ERR); echo OK' 'OK'
231 echeck
'(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
232 echeck
'(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
234 # shift (PR bin/37493)
235 dcheck
'(set -e; shift || true; echo OK); echo OK' 'OK OK'
236 echeck
'(set -e; shift || true; echo OK); echo OK' 'OK OK'
240 if [ "x$SH_FAILS" != x
]; then
241 printf '%-56s %-8s %s\n' "Expression" "Result" "Should be"
243 atf_fail
"$failcount of $count failed cases"
249 atf_init_test_cases
() {
250 atf_add_test_case all