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