t_set_e.sh revision 1.2 1 1.2 christos # $NetBSD: t_set_e.sh,v 1.2 2016/03/08 14:20:22 christos Exp $
2 1.1 jruoho #
3 1.1 jruoho # Copyright (c) 2007 The NetBSD Foundation, Inc.
4 1.1 jruoho # All rights reserved.
5 1.1 jruoho #
6 1.1 jruoho # Redistribution and use in source and binary forms, with or without
7 1.1 jruoho # modification, are permitted provided that the following conditions
8 1.1 jruoho # are met:
9 1.1 jruoho # 1. Redistributions of source code must retain the above copyright
10 1.1 jruoho # notice, this list of conditions and the following disclaimer.
11 1.1 jruoho # 2. Redistributions in binary form must reproduce the above copyright
12 1.1 jruoho # notice, this list of conditions and the following disclaimer in the
13 1.1 jruoho # documentation and/or other materials provided with the distribution.
14 1.1 jruoho #
15 1.1 jruoho # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 1.1 jruoho # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 1.1 jruoho # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 1.1 jruoho # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 1.1 jruoho # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 1.1 jruoho # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 1.1 jruoho # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 1.1 jruoho # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 1.1 jruoho # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 1.1 jruoho # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 jruoho # POSSIBILITY OF SUCH DAMAGE.
26 1.1 jruoho #
27 1.1 jruoho
28 1.1 jruoho # references:
29 1.1 jruoho # http://www.opengroup.org/onlinepubs/009695399/utilities/set.html
30 1.1 jruoho # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
31 1.1 jruoho
32 1.1 jruoho # the implementation of "sh" to test
33 1.2 christos : ${TEST_SH:="/bin/sh"}
34 1.1 jruoho
35 1.1 jruoho failwith()
36 1.1 jruoho {
37 1.1 jruoho case "$SH_FAILS" in
38 1.1 jruoho "") SH_FAILS=`echo "$1"`;;
39 1.1 jruoho *) SH_FAILS="$SH_FAILS"`echo; echo "$1"`;;
40 1.1 jruoho esac
41 1.1 jruoho }
42 1.1 jruoho
43 1.1 jruoho check1()
44 1.1 jruoho {
45 1.1 jruoho #echo "$TEST_SH -c $1"
46 1.1 jruoho result=`$TEST_SH -c "$1" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//'`
47 1.1 jruoho if [ "$result" != "$2" ]; then
48 1.1 jruoho MSG=`printf "%-56s %-8s %s" "$3" "$result" "$2"`
49 1.1 jruoho failwith "$MSG"
50 1.1 jruoho failcount=`expr $failcount + 1`
51 1.1 jruoho fi
52 1.1 jruoho count=`expr $count + 1`
53 1.1 jruoho }
54 1.1 jruoho
55 1.1 jruoho # direct check: try the given expression.
56 1.1 jruoho dcheck()
57 1.1 jruoho {
58 1.1 jruoho check1 "$1" "$2" "$1"
59 1.1 jruoho }
60 1.1 jruoho
61 1.1 jruoho # eval check: indirect through eval.
62 1.1 jruoho # as of this writing, this changes the behavior pretty drastically and
63 1.1 jruoho # is thus important to test. (PR bin/29861)
64 1.1 jruoho echeck()
65 1.1 jruoho {
66 1.1 jruoho check1 'eval '"'($1)'" "$2" "eval '($1)'"
67 1.1 jruoho }
68 1.1 jruoho
69 1.1 jruoho atf_test_case all
70 1.1 jruoho all_head() {
71 1.1 jruoho atf_set "descr" "Tests that 'set -e' works correctly"
72 1.1 jruoho }
73 1.1 jruoho all_body() {
74 1.1 jruoho count=0
75 1.1 jruoho failcount=0
76 1.1 jruoho
77 1.1 jruoho # make sure exiting from a subshell behaves as expected
78 1.1 jruoho dcheck '(set -e; exit 1; echo ERR$?); echo OK$?' 'OK1'
79 1.1 jruoho echeck '(set -e; exit 1; echo ERR$?); echo OK$?' 'OK1'
80 1.1 jruoho
81 1.1 jruoho # first, check basic functioning.
82 1.1 jruoho # The ERR shouldn't print; the result of the () should be 1.
83 1.1 jruoho # Henceforth we'll assume that we don't need to check $?.
84 1.1 jruoho dcheck '(set -e; false; echo ERR$?); echo -n OK$?' 'OK1'
85 1.1 jruoho echeck '(set -e; false; echo ERR$?); echo -n OK$?' 'OK1'
86 1.1 jruoho
87 1.1 jruoho # these cases should be equivalent to the preceding.
88 1.1 jruoho dcheck '(set -e; /nonexistent; echo ERR); echo OK' 'OK'
89 1.1 jruoho echeck '(set -e; /nonexistent; echo ERR); echo OK' 'OK'
90 1.1 jruoho dcheck '(set -e; nonexistent-program-on-path; echo ERR); echo OK' 'OK'
91 1.1 jruoho echeck '(set -e; nonexistent-program-on-path; echo ERR); echo OK' 'OK'
92 1.1 jruoho dcheck 'f() { false; }; (set -e; f; echo ERR); echo OK' 'OK'
93 1.1 jruoho echeck 'f() { false; }; (set -e; f; echo ERR); echo OK' 'OK'
94 1.1 jruoho dcheck 'f() { return 1; }; (set -e; f; echo ERR); echo OK' 'OK'
95 1.1 jruoho echeck 'f() { return 1; }; (set -e; f; echo ERR); echo OK' 'OK'
96 1.1 jruoho
97 1.1 jruoho # but! with set -e, the false should cause an *immediate* exit.
98 1.1 jruoho # The return form should not, as such, but there's no way to
99 1.1 jruoho # distinguish it.
100 1.1 jruoho dcheck 'f() { false; echo ERR; }; (set -e; f); echo OK' 'OK'
101 1.1 jruoho echeck 'f() { false; echo ERR; }; (set -e; f); echo OK' 'OK'
102 1.1 jruoho
103 1.1 jruoho # set is not scoped, so these should not exit at all.
104 1.1 jruoho dcheck 'f() { set +e; false; echo OK; }; (set -e; f); echo OK' 'OK OK'
105 1.1 jruoho echeck 'f() { set +e; false; echo OK; }; (set -e; f); echo OK' 'OK OK'
106 1.1 jruoho
107 1.1 jruoho # according to the standard, only failing *simple* commands
108 1.1 jruoho # cause an exit under -e. () is not a simple command.
109 1.1 jruoho # Correct (per POSIX):
110 1.1 jruoho #dcheck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK OK'
111 1.1 jruoho #echeck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK OK'
112 1.1 jruoho # Wrong current behavior:
113 1.1 jruoho dcheck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK'
114 1.1 jruoho echeck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK'
115 1.1 jruoho
116 1.1 jruoho # make sure an inner nested shell does exit though.
117 1.1 jruoho dcheck '(set -e; (false; echo ERR)); echo OK' 'OK'
118 1.1 jruoho
119 1.1 jruoho # The left hand side of an || or && is explicitly tested and
120 1.1 jruoho # thus should not cause an exit. Furthermore, because a || or
121 1.1 jruoho # && expression is not a simple command, there should be no
122 1.1 jruoho # exit even if the overall result is false.
123 1.1 jruoho dcheck '(set -e; false || true; echo OK); echo OK' 'OK OK'
124 1.1 jruoho echeck '(set -e; false || true; echo OK); echo OK' 'OK OK'
125 1.1 jruoho dcheck '(set -e; false && true; echo OK); echo OK' 'OK OK'
126 1.1 jruoho echeck '(set -e; false && true; echo OK); echo OK' 'OK OK'
127 1.1 jruoho
128 1.1 jruoho # However, the right hand side is not tested, so a failure
129 1.1 jruoho # there *should* cause an exit, regardless of whether it
130 1.1 jruoho # appears inside a non-simple command.
131 1.1 jruoho #
132 1.1 jruoho # Note that in at least one place the standard does not
133 1.1 jruoho # distinguish between the left and right hand sides of
134 1.1 jruoho # logical operators. It is possible that for strict
135 1.1 jruoho # compliance these need to not exit; however, if so that
136 1.1 jruoho # should probably be limited to when some strict-posix setting
137 1.1 jruoho # is in effect and tested accordingly.
138 1.1 jruoho #
139 1.1 jruoho dcheck '(set -e; false || false; echo ERR); echo OK' 'OK'
140 1.1 jruoho dcheck '(set -e; true && false; echo ERR); echo OK' 'OK'
141 1.1 jruoho echeck '(set -e; false || false; echo ERR); echo OK' 'OK'
142 1.1 jruoho echeck '(set -e; true && false; echo ERR); echo OK' 'OK'
143 1.1 jruoho
144 1.1 jruoho # correct:
145 1.1 jruoho #dcheck '(set -e; false && false; echo ERR); echo OK' 'OK'
146 1.1 jruoho #echeck '(set -e; false && false; echo ERR); echo OK' 'OK'
147 1.1 jruoho
148 1.1 jruoho # wrong current behavior:
149 1.1 jruoho dcheck '(set -e; false && false; echo ERR); echo OK' 'ERR OK'
150 1.1 jruoho echeck '(set -e; false && false; echo ERR); echo OK' 'ERR OK'
151 1.1 jruoho
152 1.1 jruoho # A failure that is not reached because of short-circuit
153 1.1 jruoho # evaluation should not cause an exit, however.
154 1.1 jruoho dcheck '(set -e; true || false; echo OK); echo OK' 'OK OK'
155 1.1 jruoho echeck '(set -e; true || false; echo OK); echo OK' 'OK OK'
156 1.1 jruoho
157 1.1 jruoho # For completeness, test the other two combinations.
158 1.1 jruoho dcheck '(set -e; true || true; echo OK); echo OK' 'OK OK'
159 1.1 jruoho dcheck '(set -e; true && true; echo OK); echo OK' 'OK OK'
160 1.1 jruoho echeck '(set -e; true || true; echo OK); echo OK' 'OK OK'
161 1.1 jruoho echeck '(set -e; true && true; echo OK); echo OK' 'OK OK'
162 1.1 jruoho
163 1.1 jruoho # likewise, none of these should exit.
164 1.1 jruoho dcheck '(set -e; while false; do :; done; echo OK); echo OK' 'OK OK'
165 1.1 jruoho dcheck '(set -e; if false; then :; fi; echo OK); echo OK' 'OK OK'
166 1.1 jruoho # problematic :-)
167 1.1 jruoho #dcheck '(set -e; until false; do :; done; echo OK); echo OK' 'OK OK'
168 1.1 jruoho dcheck '(set -e; until [ "$t" = 1 ]; do t=1; done; echo OK); echo OK' \
169 1.1 jruoho 'OK OK'
170 1.1 jruoho echeck '(set -e; while false; do :; done; echo OK); echo OK' 'OK OK'
171 1.1 jruoho echeck '(set -e; if false; then :; fi; echo OK); echo OK' 'OK OK'
172 1.1 jruoho echeck '(set -e; until [ "$t" = 1 ]; do t=1; done; echo OK); echo OK' \
173 1.1 jruoho 'OK OK'
174 1.1 jruoho
175 1.1 jruoho # the bang operator tests its argument and thus the argument
176 1.1 jruoho # should not cause an exit. it is also not a simple command (I
177 1.1 jruoho # believe) so it also shouldn't exit even if it yields a false
178 1.1 jruoho # result.
179 1.1 jruoho dcheck '(set -e; ! false; echo OK); echo OK' 'OK OK'
180 1.1 jruoho dcheck '(set -e; ! true; echo OK); echo OK' 'OK OK'
181 1.1 jruoho echeck '(set -e; ! false; echo OK); echo OK' 'OK OK'
182 1.1 jruoho echeck '(set -e; ! true; echo OK); echo OK' 'OK OK'
183 1.1 jruoho
184 1.1 jruoho # combined case with () and &&; the inner expression is false
185 1.1 jruoho # but does not itself exit, and the () should not cause an
186 1.1 jruoho # exit even when failing.
187 1.1 jruoho # correct:
188 1.1 jruoho #dcheck '(set -e; (false && true); echo OK); echo OK' 'OK OK'
189 1.1 jruoho #echeck '(set -e; (false && true); echo OK); echo OK' 'OK OK'
190 1.1 jruoho # wrong current behavior:
191 1.1 jruoho dcheck '(set -e; (false && true); echo OK); echo OK' 'OK'
192 1.1 jruoho echeck '(set -e; (false && true); echo OK); echo OK' 'OK'
193 1.1 jruoho
194 1.1 jruoho # pipelines. only the right-hand end is significant.
195 1.1 jruoho dcheck '(set -e; false | true; echo OK); echo OK' 'OK OK'
196 1.1 jruoho echeck '(set -e; false | true; echo OK); echo OK' 'OK OK'
197 1.1 jruoho dcheck '(set -e; true | false; echo ERR); echo OK' 'OK'
198 1.1 jruoho echeck '(set -e; true | false; echo ERR); echo OK' 'OK'
199 1.1 jruoho
200 1.1 jruoho dcheck '(set -e; while true | false; do :; done; echo OK); echo OK' \
201 1.1 jruoho 'OK OK'
202 1.1 jruoho dcheck '(set -e; if true | false; then :; fi; echo OK); echo OK' \
203 1.1 jruoho 'OK OK'
204 1.1 jruoho
205 1.1 jruoho
206 1.1 jruoho # According to dsl@ in PR bin/32282, () is not defined as a
207 1.1 jruoho # subshell, only as a grouping operator [and a scope, I guess]
208 1.2 christos
209 1.2 christos # (This is incorrect. () is definitely a sub-shell)
210 1.2 christos
211 1.1 jruoho # so the nested false ought to cause the whole shell to exit,
212 1.1 jruoho # not just the subshell. dholland@ would like to see C&V,
213 1.1 jruoho # because that seems like a bad idea. (Among other things, it
214 1.1 jruoho # would break all the above test logic, which relies on being
215 1.1 jruoho # able to isolate set -e behavior inside ().) However, I'm
216 1.1 jruoho # going to put these tests here to make sure the issue gets
217 1.1 jruoho # dealt with sometime.
218 1.1 jruoho #
219 1.1 jruoho # XXX: the second set has been disabled in the name of making
220 1.1 jruoho # all tests "pass".
221 1.2 christos #
222 1.2 christos # As they should be, they are utter nonsense.
223 1.1 jruoho
224 1.2 christos # 1. error if the whole shell exits (current correct behavior)
225 1.1 jruoho dcheck 'echo OK; (set -e; false); echo OK' 'OK OK'
226 1.1 jruoho echeck 'echo OK; (set -e; false); echo OK' 'OK OK'
227 1.1 jruoho # 2. error if the whole shell does not exit (dsl's suggested behavior)
228 1.1 jruoho #dcheck 'echo OK; (set -e; false); echo ERR' 'OK'
229 1.1 jruoho #echeck 'echo OK; (set -e; false); echo ERR' 'OK'
230 1.1 jruoho
231 1.1 jruoho # The current behavior of the shell is that it exits out as
232 1.1 jruoho # far as -e is set and then stops. This is probably a
233 1.1 jruoho # consequence of it handling () wrong, but it's a somewhat
234 1.1 jruoho # curious compromise position between 1. and 2. above.
235 1.1 jruoho dcheck '(set -e; (false; echo ERR); echo ERR); echo OK' 'OK'
236 1.1 jruoho echeck '(set -e; (false; echo ERR); echo ERR); echo OK' 'OK'
237 1.1 jruoho
238 1.1 jruoho # backquote expansion (PR bin/17514)
239 1.1 jruoho
240 1.2 christos # (in-)correct
241 1.1 jruoho #dcheck '(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
242 1.1 jruoho #dcheck '(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
243 1.1 jruoho #dcheck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
244 1.1 jruoho #dcheck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
245 1.2 christos # Not-wrong current behavior
246 1.2 christos # the exit status of ommand substitution is ignored in most cases
247 1.2 christos # None of these should be causing the shell to exit.
248 1.1 jruoho dcheck '(set -e; echo ERR `false`; echo ERR); echo OK' 'ERR ERR OK'
249 1.1 jruoho dcheck '(set -e; echo ERR $(false); echo ERR); echo OK' 'ERR ERR OK'
250 1.1 jruoho dcheck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'ERR ERR OK'
251 1.1 jruoho dcheck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'ERR ERR OK'
252 1.1 jruoho
253 1.2 christos # This is testing one case (the case?) where the exit status is used
254 1.1 jruoho dcheck '(set -e; x=`false`; echo ERR); echo OK' 'OK'
255 1.1 jruoho dcheck '(set -e; x=$(false); echo ERR); echo OK' 'OK'
256 1.1 jruoho dcheck '(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
257 1.1 jruoho dcheck '(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
258 1.1 jruoho
259 1.2 christos # correct (really just commented out incorrect nonsense)
260 1.1 jruoho #echeck '(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
261 1.1 jruoho #echeck '(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
262 1.1 jruoho #echeck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
263 1.1 jruoho #echeck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
264 1.1 jruoho
265 1.2 christos # not-wrong current behavior (as above)
266 1.1 jruoho echeck '(set -e; echo ERR `false`; echo ERR); echo OK' 'ERR ERR OK'
267 1.1 jruoho echeck '(set -e; echo ERR $(false); echo ERR); echo OK' 'ERR ERR OK'
268 1.1 jruoho echeck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'ERR ERR OK'
269 1.1 jruoho echeck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'ERR ERR OK'
270 1.1 jruoho
271 1.1 jruoho echeck '(set -e; x=`false`; echo ERR); echo OK' 'OK'
272 1.1 jruoho echeck '(set -e; x=$(false); echo ERR); echo OK' 'OK'
273 1.1 jruoho echeck '(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
274 1.1 jruoho echeck '(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
275 1.1 jruoho
276 1.1 jruoho # shift (PR bin/37493)
277 1.1 jruoho # correct
278 1.2 christos # Actually, both ways are correct, both are permitted
279 1.1 jruoho #dcheck '(set -e; shift || true; echo OK); echo OK' 'OK OK'
280 1.1 jruoho #echeck '(set -e; shift || true; echo OK); echo OK' 'OK OK'
281 1.2 christos # (not-) wrong current behavior
282 1.2 christos #dcheck '(set -e; shift || true; echo OK); echo OK' 'OK'
283 1.2 christos #echeck '(set -e; shift || true; echo OK); echo OK' 'OK'
284 1.2 christos
285 1.2 christos # what is wrong is this test assuming one behaviour or the other
286 1.2 christos # (and incidentally this has nothing whatever to do with "-e",
287 1.2 christos # the test should really be moved elsewhere...)
288 1.2 christos # But for now, leave it here, and correct it:
289 1.2 christos dcheck '(set -e; shift && echo OK); echo OK' 'OK'
290 1.2 christos echeck '(set -e; shift && echo OK); echo OK' 'OK'
291 1.1 jruoho
292 1.1 jruoho # Done.
293 1.1 jruoho
294 1.1 jruoho if [ "x$SH_FAILS" != x ]; then
295 1.1 jruoho printf '%-56s %-8s %s\n' "Expression" "Result" "Should be"
296 1.1 jruoho echo "$SH_FAILS"
297 1.1 jruoho atf_fail "$failcount of $count failed cases"
298 1.1 jruoho else
299 1.1 jruoho atf_pass
300 1.1 jruoho fi
301 1.1 jruoho }
302 1.1 jruoho
303 1.1 jruoho atf_init_test_cases() {
304 1.1 jruoho atf_add_test_case all
305 1.1 jruoho }
306