OILS / spec / errexit.test.sh View on Github | oilshell.org

393 lines, 208 significant
1#
2# Usage:
3# ./errexit.test.sh <function name>
4
5#### errexit aborts early
6set -o errexit
7false
8echo done
9## stdout-json: ""
10## status: 1
11
12#### errexit for nonexistent command
13set -o errexit
14nonexistent__ZZ
15echo done
16## stdout-json: ""
17## status: 127
18
19#### errexit aborts early on pipeline
20set -o errexit
21echo hi | grep nonexistent
22echo two
23## stdout-json: ""
24## status: 1
25
26#### errexit with { }
27# This aborts because it's not part of an if statement.
28set -o errexit
29{ echo one; false; echo two; }
30## stdout: one
31## status: 1
32
33#### errexit with if and { }
34set -o errexit
35if { echo one; false; echo two; }; then
36 echo three
37fi
38echo four
39## status: 0
40## STDOUT:
41one
42two
43three
44four
45## END
46
47#### errexit with ||
48set -o errexit
49echo hi | grep nonexistent || echo ok
50## stdout: ok
51## status: 0
52
53#### errexit with &&
54set -o errexit
55echo ok && echo hi | grep nonexistent
56## stdout: ok
57## status: 1
58
59#### errexit test && -- from gen-module-init
60set -o errexit
61test "$mod" = readline && echo "#endif"
62echo status=$?
63## stdout: status=1
64
65#### errexit test && and fail
66set -o errexit
67test -n X && false
68echo status=$?
69## stdout-json: ""
70## status: 1
71
72#### errexit and loop
73set -o errexit
74for x in 1 2 3; do
75 test $x = 2 && echo "hi $x"
76done
77## stdout: hi 2
78## status: 1
79
80#### errexit and brace group { }
81set -o errexit
82{ test no = yes && echo hi; }
83echo status=$?
84## stdout: status=1
85
86#### errexit and time { }
87set -o errexit
88time false
89echo status=$?
90## status: 1
91
92#### errexit with !
93set -o errexit
94echo one
95! true
96echo two
97! false
98echo three
99## STDOUT:
100one
101two
102three
103## END
104
105#### errexit with ! and ;
106# AST has extra Sentence nodes; there was a REGRESSION here.
107set -o errexit; echo one; ! true; echo two; ! false; echo three
108## STDOUT:
109one
110two
111three
112## END
113
114#### errexit with while/until
115set -o errexit
116while false; do
117 echo ok
118done
119until false; do
120 echo ok # do this once then exit loop
121 break
122done
123## stdout: ok
124## status: 0
125
126#### errexit with (( ))
127# from http://mywiki.wooledge.org/BashFAQ/105, this changed between versions.
128# ash says that 'i++' is not found, but it doesn't exit. I guess this is the
129# subshell problem?
130set -o errexit
131i=0
132(( i++ ))
133echo done
134## stdout-json: ""
135## status: 1
136## N-I dash/ash status: 127
137## N-I dash/ash stdout-json: ""
138
139#### errexit with subshell
140set -o errexit
141( echo one; false; echo two; )
142echo three
143## status: 1
144## STDOUT:
145one
146## END
147
148#### set -o errexit while it's being ignored (moot with strict_errexit)
149set -o errexit
150# osh aborts early here
151if { echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; }; then
152 echo 5;
153fi
154echo 6
155false # this is the one that makes shells fail
156echo 7
157## status: 1
158## STDOUT:
1591
1602
1613
1624
1635
1646
165## END
166
167#### set +o errexit while it's being ignored (moot with strict_errexit)
168set -o errexit
169if { echo 1; false; echo 2; set +o errexit; echo 3; false; echo 4; }; then
170 echo 5;
171fi
172echo 6
173false # does NOT fail, because we restored it.
174echo 7
175## STDOUT:
1761
1772
1783
1794
1805
1816
1827
183## END
184
185#### set +o errexit with 2 levels of ignored
186set -o errexit
187if { echo 1; ! set +o errexit; echo 2; }; then
188 echo 3
189fi
190echo 6
191false
192echo 7
193
194## STDOUT:
1951
1962
1973
1986
1997
200## END
201
202#### setting errexit in a subshell works but doesn't affect parent shell
203( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; )
204echo 5
205false
206echo 6
207## STDOUT:
2081
2092
2103
2115
2126
213## END
214
215#### set errexit while it's ignored in a subshell (moot with strict_errexit)
216set -o errexit
217if ( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4 ); then
218 echo 5;
219fi
220echo 6 # This is executed because the subshell just returns false
221false
222echo 7
223## status: 1
224## STDOUT:
2251
2262
2273
2284
2295
2306
231## END
232
233#### shopt -s strict:all || true while errexit is on
234set -o errexit
235shopt -s strict:all || true
236echo one
237false # fail
238echo two
239## status: 1
240## STDOUT:
241one
242## END
243
244#### errexit double guard
245# OSH bug fix. ErrExit needs a counter, not a boolean.
246set -o errexit
247if { ! false; false; true; } then
248 echo true
249fi
250false
251echo done
252## status: 1
253## STDOUT:
254true
255## END
256
257#### background processes respect errexit
258set -o errexit
259{ echo one; false; echo two; exit 42; } &
260wait $!
261## status: 1
262## STDOUT:
263one
264## END
265
266#### pipeline process respects errexit
267set -o errexit
268# It is respected here.
269{ echo one; false; echo two; } | cat
270
271# Also respected here.
272{ echo three; echo four; } | while read line; do
273 echo "[$line]"
274 false
275done
276echo four
277## status: 1
278## STDOUT:
279one
280[three]
281## END
282
283#### compound command
284# case from
285# https://lists.gnu.org/archive/html/bug-bash/2020-05/msg00066.html
286
287set -o errexit
288
289{ cat ; } < not_exist.txt
290
291echo status=$?
292echo 'should not get here'
293## status: 1
294## stdout-json: ""
295## BUG dash/bash/ash status: 0
296## BUG bash/ash STDOUT:
297status=1
298should not get here
299## END
300## BUG dash STDOUT:
301status=2
302should not get here
303## END
304
305#### while loop
306# case from
307# https://lists.gnu.org/archive/html/bug-bash/2020-05/msg00066.html
308
309set -o errexit
310
311while read line; do
312 echo $line
313done < not_exist.txt
314
315echo status=$?
316echo 'should not get here'
317## status: 1
318## stdout-json: ""
319## BUG dash/bash/ash status: 0
320## BUG bash/ash STDOUT:
321status=1
322should not get here
323## END
324## BUG dash STDOUT:
325status=2
326should not get here
327## END
328
329#### set -e enabled in function (regression)
330foo() {
331 set -e
332 false
333 echo "should be executed"
334}
335#foo && true
336#foo || true
337
338if foo; then
339 true
340fi
341
342echo "should be executed"
343## STDOUT:
344should be executed
345should be executed
346## END
347
348#### set -e in function #2
349foo() {
350 set -e
351 false
352 echo "should be executed"
353}
354! foo
355
356echo "should be executed"
357## BUG bash stdout-json: ""
358## BUG bash status: 1
359## STDOUT:
360should be executed
361should be executed
362## END
363
364
365#### Command sub exit code is lost
366echo ft $(false) $(true)
367echo status=$?
368
369set -o errexit
370shopt -s inherit_errexit || true
371
372# This changes it
373#shopt -s command_sub_errexit || true
374
375echo f $(date %x)
376echo status=$?
377
378# compare with
379# x=$(date %x) # FAILS
380# local x=$(date %x) # does NOT fail
381
382echo ft $(false) $(true)
383echo status=$?
384
385## STDOUT:
386ft
387status=0
388f
389status=0
390ft
391status=0
392## END
393