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

500 lines, 240 significant
1## compare_shells: dash bash-4.4 mksh ash
2## oils_failures_allowed: 0
3
4# TODO: upgrade to bash 5.2 and make OSH behave like that! redirect failures
5
6#### errexit aborts early
7set -o errexit
8false
9echo done
10## stdout-json: ""
11## status: 1
12
13#### errexit for nonexistent command
14set -o errexit
15nonexistent__ZZ
16echo done
17## stdout-json: ""
18## status: 127
19
20#### errexit aborts early on pipeline
21set -o errexit
22echo hi | grep nonexistent
23echo two
24## stdout-json: ""
25## status: 1
26
27#### errexit with { }
28# This aborts because it's not part of an if statement.
29set -o errexit
30{ echo one; false; echo two; }
31## stdout: one
32## status: 1
33
34#### errexit with if and { }
35set -o errexit
36if { echo one; false; echo two; }; then
37 echo three
38fi
39echo four
40## status: 0
41## STDOUT:
42one
43two
44three
45four
46## END
47
48#### errexit with ||
49set -o errexit
50echo hi | grep nonexistent || echo ok
51## stdout: ok
52## status: 0
53
54#### errexit with &&
55set -o errexit
56echo ok && echo hi | grep nonexistent
57## stdout: ok
58## status: 1
59
60#### errexit test && -- from gen-module-init
61set -o errexit
62test "$mod" = readline && echo "#endif"
63echo status=$?
64## stdout: status=1
65
66#### errexit test && and fail
67set -o errexit
68test -n X && false
69echo status=$?
70## stdout-json: ""
71## status: 1
72
73#### errexit and loop
74set -o errexit
75for x in 1 2 3; do
76 test $x = 2 && echo "hi $x"
77done
78## stdout: hi 2
79## status: 1
80
81#### errexit and brace group { }
82set -o errexit
83{ test no = yes && echo hi; }
84echo status=$?
85## stdout: status=1
86
87#### errexit and time { }
88set -o errexit
89time false
90echo status=$?
91## status: 1
92
93#### errexit with !
94set -o errexit
95echo one
96! true
97echo two
98! false
99echo three
100## STDOUT:
101one
102two
103three
104## END
105
106#### errexit with ! and ;
107# AST has extra Sentence nodes; there was a REGRESSION here.
108set -o errexit; echo one; ! true; echo two; ! false; echo three
109## STDOUT:
110one
111two
112three
113## END
114
115#### errexit with while/until
116set -o errexit
117while false; do
118 echo ok
119done
120until false; do
121 echo ok # do this once then exit loop
122 break
123done
124## stdout: ok
125## status: 0
126
127#### errexit with (( ))
128# from http://mywiki.wooledge.org/BashFAQ/105, this changed between versions.
129# ash says that 'i++' is not found, but it doesn't exit. I guess this is the
130# subshell problem?
131set -o errexit
132i=0
133(( i++ ))
134echo done
135## stdout-json: ""
136## status: 1
137## N-I dash/ash status: 127
138## N-I dash/ash stdout-json: ""
139
140#### errexit with subshell
141set -o errexit
142( echo one; false; echo two; )
143echo three
144## status: 1
145## STDOUT:
146one
147## END
148
149#### set -o errexit while it's being ignored (moot with strict_errexit)
150set -o errexit
151# osh aborts early here
152if { echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; }; then
153 echo 5;
154fi
155echo 6
156false # this is the one that makes shells fail
157echo 7
158## status: 1
159## STDOUT:
1601
1612
1623
1634
1645
1656
166## END
167
168#### set +o errexit while it's being ignored (moot with strict_errexit)
169set -o errexit
170if { echo 1; false; echo 2; set +o errexit; echo 3; false; echo 4; }; then
171 echo 5;
172fi
173echo 6
174false # does NOT fail, because we restored it.
175echo 7
176## STDOUT:
1771
1782
1793
1804
1815
1826
1837
184## END
185
186#### set +o errexit with 2 levels of ignored
187set -o errexit
188if { echo 1; ! set +o errexit; echo 2; }; then
189 echo 3
190fi
191echo 6
192false
193echo 7
194
195## STDOUT:
1961
1972
1983
1996
2007
201## END
202
203#### setting errexit in a subshell works but doesn't affect parent shell
204( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; )
205echo 5
206false
207echo 6
208## STDOUT:
2091
2102
2113
2125
2136
214## END
215
216#### set errexit while it's ignored in a subshell (moot with strict_errexit)
217set -o errexit
218if ( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4 ); then
219 echo 5;
220fi
221echo 6 # This is executed because the subshell just returns false
222false
223echo 7
224## status: 1
225## STDOUT:
2261
2272
2283
2294
2305
2316
232## END
233
234#### shopt -s strict:all || true while errexit is on
235set -o errexit
236shopt -s strict:all || true
237echo one
238false # fail
239echo two
240## status: 1
241## STDOUT:
242one
243## END
244
245#### errexit double guard
246# OSH bug fix. ErrExit needs a counter, not a boolean.
247set -o errexit
248if { ! false; false; true; } then
249 echo true
250fi
251false
252echo done
253## status: 1
254## STDOUT:
255true
256## END
257
258#### background processes respect errexit
259set -o errexit
260{ echo one; false; echo two; exit 42; } &
261wait $!
262## status: 1
263## STDOUT:
264one
265## END
266
267#### pipeline process respects errexit
268set -o errexit
269# It is respected here.
270{ echo one; false; echo two; } | cat
271
272# Also respected here.
273{ echo three; echo four; } | while read line; do
274 echo "[$line]"
275 false
276done
277echo four
278## status: 1
279## STDOUT:
280one
281[three]
282## END
283
284#### simple command / assign - redir failure DOES respect errexit
285
286$SH -c '
287set -o errexit
288true > /
289echo builtin status=$?
290'
291echo status=$?
292
293$SH -c '
294set -o errexit
295/bin/true > /
296echo extern status=$?
297'
298echo status=$?
299
300$SH -c '
301set -o errexit
302assign=foo > /
303echo assign status=$?
304'
305echo status=$?
306
307## STDOUT:
308status=1
309status=1
310status=1
311## END
312## OK dash STDOUT:
313status=2
314status=2
315status=2
316## END
317
318#### simple command that's an alias -- redir failure NOT checked
319
320$SH -c '
321shopt -s expand_aliases
322
323set -o errexit
324alias zz="{ echo 1; echo 2; }"
325zz > /
326echo alias status=$?
327'
328echo status=$?
329
330## STDOUT:
331alias status=1
332status=0
333## END
334
335## OK dash STDOUT:
336alias status=2
337status=0
338## END
339
340## BUG mksh STDOUT:
341status=1
342## END
343
344#### bash atoms [[ (( - redir failure does NOT respect errexit (unless redir_errexit)
345case $SH in dash) exit ;; esac
346
347$SH -c '
348set -o errexit
349[[ x = x ]] > /
350echo dbracket status=$?
351'
352echo status=$?
353
354$SH -c '
355set -o errexit
356(( 42 )) > /
357echo dparen status=$?
358'
359echo status=$?
360
361## STDOUT:
362dbracket status=1
363status=0
364dparen status=1
365status=0
366## END
367
368# mksh checks errors!
369
370## OK mksh STDOUT:
371status=1
372status=1
373## END
374
375## OK ash STDOUT:
376status=1
377status=2
378## END
379
380## N-I dash STDOUT:
381## END
382
383
384#### brace group - redir failure does NOT respect errexit
385# case from
386# https://lists.gnu.org/archive/html/bug-bash/2020-05/msg00066.html
387
388set -o errexit
389
390{ cat ; } < not_exist.txt
391
392echo status=$?
393echo 'should not get here'
394
395## STDOUT:
396status=1
397should not get here
398## END
399
400## OK dash STDOUT:
401status=2
402should not get here
403## END
404
405## BUG mksh status: 1
406## BUG mksh STDOUT:
407## END
408
409#### while loop - redirect failure does NOT respect errexit
410# case from
411# https://lists.gnu.org/archive/html/bug-bash/2020-05/msg00066.html
412
413set -o errexit
414
415while read line; do
416 echo $line
417done < not_exist.txt
418
419echo status=$?
420echo 'should not get here'
421
422## STDOUT:
423status=1
424should not get here
425## END
426
427## OK dash STDOUT:
428status=2
429should not get here
430## END
431
432## BUG mksh status: 1
433## BUG mksh STDOUT:
434## END
435
436#### set -e enabled in function (regression)
437foo() {
438 set -e
439 false
440 echo "should be executed"
441}
442#foo && true
443#foo || true
444
445if foo; then
446 true
447fi
448
449echo "should be executed"
450## STDOUT:
451should be executed
452should be executed
453## END
454
455#### set -e in function #2
456foo() {
457 set -e
458 false
459 echo "should be executed"
460}
461! foo
462
463echo "should be executed"
464## BUG bash stdout-json: ""
465## BUG bash status: 1
466## STDOUT:
467should be executed
468should be executed
469## END
470
471
472#### Command sub exit code is lost
473echo ft $(false) $(true)
474echo status=$?
475
476set -o errexit
477shopt -s inherit_errexit || true
478
479# This changes it
480#shopt -s command_sub_errexit || true
481
482echo f $(date %x)
483echo status=$?
484
485# compare with
486# x=$(date %x) # FAILS
487# local x=$(date %x) # does NOT fail
488
489echo ft $(false) $(true)
490echo status=$?
491
492## STDOUT:
493ft
494status=0
495f
496status=0
497ft
498status=0
499## END
500