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

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