OILS / spec / builtin-trap-err.test.sh View on Github | oilshell.org

480 lines, 242 significant
1## oils_failures_allowed: 2
2## compare_shells: bash mksh ash
3
4# Notes on bash semantics:
5#
6# https://www.gnu.org/software/bash/manual/bash.html
7#
8# The trap builtin (see Bourne Shell Builtins) allows an ERR pseudo-signal
9# specification, similar to EXIT and DEBUG. Commands specified with an ERR trap
10# are executed after a simple command fails, with a few exceptions. The ERR
11# trap is not inherited by shell functions unless the -o errtrace option to the
12# set builtin is enabled.
13
14
15#### trap can use original $LINENO
16
17trap 'echo line=$LINENO' ERR
18
19false
20false
21echo ok
22
23## STDOUT:
24line=3
25line=4
26ok
27## END
28
29#### trap ERR and set -o errexit
30
31trap 'echo line=$LINENO' ERR
32
33false
34echo a
35
36set -o errexit
37
38echo b
39false # trap executed, and executation also halts
40echo c # doesn't get here
41
42## status: 1
43## STDOUT:
44line=3
45a
46b
47line=9
48## END
49
50#### trap ERR and errexit disabled context
51
52trap 'echo line=$LINENO' ERR
53
54false
55echo a
56
57set -o errexit
58
59echo b
60if false; then
61 echo xx
62fi
63echo c # doesn't get here
64
65## STDOUT:
66line=3
67a
68b
69c
70## END
71
72#### trap ERR and if statement
73
74if test -f /nope; then echo file exists; fi
75
76trap 'echo err' ERR
77#trap 'echo line=$LINENO' ERR
78
79if test -f /nope; then echo file exists; fi
80
81## STDOUT:
82## END
83
84
85#### trap ERR and || conditional
86
87trap 'echo line=$LINENO' ERR
88
89false || false || false
90echo ok
91
92false && false
93echo ok
94
95## STDOUT:
96line=3
97ok
98ok
99## END
100
101#### trap ERR and pipeline
102
103# mksh and bash have different line numbers in this case
104#trap 'echo line=$LINENO' ERR
105trap 'echo line=$LINENO' ERR
106
107# it's run for the last 'false'
108false | false | false
109
110{ echo pipeline; false; } | false | false
111
112# it's never run here
113! true
114! false
115
116## STDOUT:
117line=3
118line=5
119## END
120
121## BUG mksh/ash STDOUT:
122line=1
123line=1
124## END
125
126
127#### trap ERR does not run in errexit situations
128
129trap 'echo line=$LINENO' ERR
130
131if false; then
132 echo if
133fi
134
135while false; do
136 echo while
137done
138
139until false; do
140 echo until
141 break
142done
143
144false || false || false
145
146false && false && false
147
148false; false; false
149
150echo ok
151
152## STDOUT:
153until
154line=16
155line=20
156line=20
157line=20
158ok
159## END
160
161
162#### trap ERR subprogram - subshell, command sub, async
163
164trap 'echo line=$LINENO' ERR
165
166( false; echo subshell )
167
168x=$( false; echo command sub )
169
170false & wait
171
172{ false; echo async; } & wait
173
174false
175echo ok
176
177## STDOUT:
178subshell
179async
180line=11
181ok
182## END
183
184#### trap ERR not active in shell functions in (bash behavior)
185
186trap 'echo line=$LINENO' ERR
187
188f() {
189 false
190 true
191}
192
193f
194
195## STDOUT:
196## END
197
198## N-I mksh STDOUT:
199line=4
200## END
201
202#### trap ERR shell function - with errtrace
203
204trap 'echo line=$LINENO' ERR
205
206passing() {
207 false # line 4
208 true
209}
210
211failing() {
212 true
213 false
214}
215
216passing
217failing
218
219set -o errtrace
220
221echo 'now with errtrace'
222passing
223failing
224
225echo ok
226
227## STDOUT:
228line=14
229now with errtrace
230line=4
231line=10
232line=20
233ok
234## END
235
236## BUG mksh status: 1
237## BUG mksh STDOUT:
238line=4
239line=10
240## END
241
242#### trap ERR with "atoms": assignment (( [[
243
244trap 'echo line=$LINENO' ERR
245
246x=$(false)
247
248[[ a == b ]]
249
250(( 0 ))
251echo ok
252
253## STDOUT:
254line=3
255line=5
256line=7
257ok
258## END
259
260## BUG mksh STDOUT:
261line=3
262line=3
263line=7
264ok
265## END
266
267
268#### trap ERR with for, case, { }
269
270trap 'echo line=$LINENO' ERR
271
272for y in 1 2; do
273 false
274done
275
276case x in
277 x) false ;;
278 *) false ;;
279esac
280
281{ false; false; }
282echo ok
283
284## STDOUT:
285line=4
286line=4
287line=8
288line=12
289line=12
290ok
291## END
292
293#### trap ERR with redirect
294
295trap 'echo line=$LINENO' ERR
296
297false
298
299{ false
300 true
301} > /zz # error
302echo ok
303
304## STDOUT:
305line=3
306line=7
307ok
308## END
309
310# doesn't update line for redirect
311
312## BUG bash/mksh STDOUT:
313line=3
314line=3
315ok
316## END
317
318## BUG ash STDOUT:
319line=3
320ok
321## END
322
323
324#### trap ERR with YSH proc
325
326case $SH in bash|mksh|ash) exit ;; esac
327
328# seems the same
329
330shopt -s ysh:upgrade
331
332proc handler {
333 echo err
334}
335
336if test -f /nope { echo file exists }
337
338trap handler ERR
339
340if test -f /nope { echo file exists }
341
342false || true # not run for the first part here
343false
344
345## status: 1
346## STDOUT:
347err
348## END
349
350## N-I bash/mksh/ash status: 0
351## N-I bash/mksh/ash STDOUT:
352## END
353
354#### trap ERR
355err() {
356 echo "err [$@] $?"
357}
358trap 'err x y' ERR
359
360echo A
361
362false
363echo B
364
365( exit 42 )
366echo C
367
368trap - ERR # disable trap
369
370false
371echo D
372
373trap 'echo after errexit $?' ERR
374
375set -o errexit
376
377( exit 99 )
378echo E
379
380## status: 99
381## STDOUT:
382A
383err [x y] 1
384B
385err [x y] 42
386C
387D
388after errexit 99
389## END
390## N-I dash STDOUT:
391A
392B
393C
394D
395## END
396
397#### trap ERR and pipelines (lastpipe and PIPESTATUS difference)
398case $SH in ash) exit ;; esac
399
400err() {
401 echo "err [$@] status=$? [${PIPESTATUS[@]}]"
402}
403trap 'err' ERR
404
405echo A
406
407false
408
409# succeeds
410echo B | grep B
411
412# fails
413echo C | grep zzz
414
415echo D | grep zzz | cat
416
417set -o pipefail
418echo E | grep zzz | cat
419
420trap - ERR # disable trap
421
422echo F | grep zz
423echo ok
424
425## STDOUT:
426A
427err [] status=1 [1]
428B
429err [] status=1 [0 1]
430err [] status=1 [0 1 0]
431ok
432## END
433
434# lastpipe semantics mean we get another call!
435# also we don't set PIPESTATUS unless we get a pipeline
436
437## OK osh STDOUT:
438A
439err [] status=1 []
440B
441err [] status=1 [0 0]
442err [] status=1 [0 1]
443err [] status=1 [0 1 0]
444ok
445## END
446
447## N-I ash STDOUT:
448## END
449
450#### error in trap ERR (recursive)
451case $SH in dash) exit ;; esac
452
453err() {
454 echo err status $?
455 false
456 ( exit 2 ) # not recursively triggered
457 echo err 2
458}
459trap 'err' ERR
460
461echo A
462false
463echo B
464
465# Try it with errexit
466set -e
467false
468echo C
469
470## status: 1
471## STDOUT:
472A
473err status 1
474err 2
475B
476err status 1
477## END
478## N-I dash STDOUT:
479## END
480