]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/netbsd-tests/bin/sh/t_set_e.sh
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / netbsd-tests / bin / sh / t_set_e.sh
1 # $NetBSD: t_set_e.sh,v 1.1 2012/03/17 16:33:11 jruoho 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:="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 -n OK$?' 'OK1'
85         echeck '(set -e; false; echo ERR$?); echo -n 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         # so the nested false ought to cause the whole shell to exit,
209         # not just the subshell. dholland@ would like to see C&V,
210         # because that seems like a bad idea. (Among other things, it
211         # would break all the above test logic, which relies on being
212         # able to isolate set -e behavior inside ().) However, I'm
213         # going to put these tests here to make sure the issue gets
214         # dealt with sometime.
215         #
216         # XXX: the second set has been disabled in the name of making
217         # all tests "pass".
218
219         # 1. error if the whole shell exits (current behavior)
220         dcheck 'echo OK; (set -e; false); echo OK' 'OK OK'
221         echeck 'echo OK; (set -e; false); echo OK' 'OK OK'
222         # 2. error if the whole shell does not exit (dsl's suggested behavior)
223         #dcheck 'echo OK; (set -e; false); echo ERR' 'OK'
224         #echeck 'echo OK; (set -e; false); echo ERR' 'OK'
225
226         # The current behavior of the shell is that it exits out as
227         # far as -e is set and then stops. This is probably a
228         # consequence of it handling () wrong, but it's a somewhat
229         # curious compromise position between 1. and 2. above.
230         dcheck '(set -e; (false; echo ERR); echo ERR); echo OK' 'OK'
231         echeck '(set -e; (false; echo ERR); echo ERR); echo OK' 'OK'
232
233         # backquote expansion (PR bin/17514)
234
235         # correct
236         #dcheck '(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
237         #dcheck '(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
238         #dcheck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
239         #dcheck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
240         # wrong current behavior
241         dcheck '(set -e; echo ERR `false`; echo ERR); echo OK' 'ERR ERR OK'
242         dcheck '(set -e; echo ERR $(false); echo ERR); echo OK' 'ERR ERR OK'
243         dcheck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'ERR ERR OK'
244         dcheck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'ERR ERR OK'
245
246         dcheck '(set -e; x=`false`; echo ERR); echo OK' 'OK'
247         dcheck '(set -e; x=$(false); echo ERR); echo OK' 'OK'
248         dcheck '(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
249         dcheck '(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
250
251         # correct
252         #echeck '(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
253         #echeck '(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
254         #echeck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
255         #echeck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
256
257         # wrong current behavior
258         echeck '(set -e; echo ERR `false`; echo ERR); echo OK' 'ERR ERR OK'
259         echeck '(set -e; echo ERR $(false); echo ERR); echo OK' 'ERR ERR OK'
260         echeck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'ERR ERR OK'
261         echeck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'ERR ERR OK'
262
263         echeck '(set -e; x=`false`; echo ERR); echo OK' 'OK'
264         echeck '(set -e; x=$(false); echo ERR); echo OK' 'OK'
265         echeck '(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
266         echeck '(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
267
268         # shift (PR bin/37493)
269         # correct
270         #dcheck '(set -e; shift || true; echo OK); echo OK' 'OK OK'
271         #echeck '(set -e; shift || true; echo OK); echo OK' 'OK OK'
272         # wrong current behavior
273         dcheck '(set -e; shift || true; echo OK); echo OK' 'OK'
274         echeck '(set -e; shift || true; echo OK); echo OK' 'OK'
275
276         # Done.
277
278         if [ "x$SH_FAILS" != x ]; then
279             printf '%-56s %-8s  %s\n' "Expression" "Result" "Should be"
280             echo "$SH_FAILS"
281             atf_fail "$failcount of $count failed cases"
282         else
283             atf_pass
284         fi
285 }
286
287 atf_init_test_cases() {
288         atf_add_test_case all
289 }