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

394 lines, 196 significant
1## oils_failures_allowed: 4
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 (regression)
86
87trap 'echo line=$LINENO' ERR
88
89false || false || false
90echo ok
91
92## STDOUT:
93line=3
94ok
95## END
96
97#### trap ERR does not run in errexit situations
98
99trap 'echo line=$LINENO' ERR
100
101if false; then
102 echo if
103fi
104
105while false; do
106 echo while
107done
108
109until false; do
110 echo until
111 break
112done
113
114false || false || false
115
116false && false && false
117
118false; false; false
119
120echo ok
121
122## STDOUT:
123until
124line=16
125line=20
126line=20
127line=20
128ok
129## END
130
131
132#### trap ERR pipeline (also errexit)
133
134# mksh and bash have different line numbers in this case
135#trap 'echo line=$LINENO' ERR
136trap 'echo line=$LINENO' ERR
137
138# it's run for the last 'false'
139false | false | false
140
141{ echo pipeline; false; } | false | false
142
143# it's never run here
144! true
145! false
146
147## STDOUT:
148line=3
149line=5
150## END
151
152## BUG mksh/ash STDOUT:
153line=1
154line=1
155## END
156
157#### trap ERR subprogram - subshell, command sub, async
158
159trap 'echo line=$LINENO' ERR
160
161( false; echo subshell )
162
163x=$( false; echo command sub )
164
165false & wait
166
167{ false; echo async; } & wait
168
169false
170echo ok
171
172## STDOUT:
173subshell
174async
175line=11
176ok
177## END
178
179#### trap ERR not active in shell functions in (bash behavior)
180
181trap 'echo line=$LINENO' ERR
182
183f() {
184 false
185 true
186}
187
188f
189
190## STDOUT:
191## END
192
193## N-I mksh STDOUT:
194line=4
195## END
196
197#### trap ERR shell function - with errtrace
198
199trap 'echo line=$LINENO' ERR
200
201passing() {
202 false # line 4
203 true
204}
205
206failing() {
207 true
208 false
209}
210
211passing
212failing
213
214set -o errtrace
215
216echo 'now with errtrace'
217passing
218failing
219
220echo ok
221
222## STDOUT:
223line=14
224now with errtrace
225line=4
226line=10
227line=20
228ok
229## END
230
231## BUG mksh status: 1
232## BUG mksh STDOUT:
233line=4
234line=10
235## END
236
237
238#### trap ERR with YSH proc
239
240case $SH in bash|mksh|ash) exit ;; esac
241
242# seems the same
243
244shopt -s ysh:upgrade
245
246proc handler {
247 echo err
248}
249
250if test -f /nope { echo file exists }
251
252trap handler ERR
253
254if test -f /nope { echo file exists }
255
256false || true # not run for the first part here
257false
258
259## status: 1
260## STDOUT:
261err
262## END
263
264## N-I bash/mksh/ash status: 0
265## N-I bash/mksh/ash STDOUT:
266## END
267
268#### trap ERR
269err() {
270 echo "err [$@] $?"
271}
272trap 'err x y' ERR
273
274echo A
275
276false
277echo B
278
279( exit 42 )
280echo C
281
282trap - ERR # disable trap
283
284false
285echo D
286
287trap 'echo after errexit $?' ERR
288
289set -o errexit
290
291( exit 99 )
292echo E
293
294## status: 99
295## STDOUT:
296A
297err [x y] 1
298B
299err [x y] 42
300C
301D
302after errexit 99
303## END
304## N-I dash STDOUT:
305A
306B
307C
308D
309## END
310
311#### trap ERR and pipelines (lastpipe and PIPESTATUS difference)
312case $SH in ash) exit ;; esac
313
314err() {
315 echo "err [$@] status=$? [${PIPESTATUS[@]}]"
316}
317trap 'err' ERR
318
319echo A
320
321false
322
323# succeeds
324echo B | grep B
325
326# fails
327echo C | grep zzz
328
329echo D | grep zzz | cat
330
331set -o pipefail
332echo E | grep zzz | cat
333
334trap - ERR # disable trap
335
336echo F | grep zz
337echo ok
338
339## STDOUT:
340A
341err [] status=1 [1]
342B
343err [] status=1 [0 1]
344err [] status=1 [0 1 0]
345ok
346## END
347
348# lastpipe semantics mean we get another call!
349# also we don't set PIPESTATUS unless we get a pipeline
350
351## OK osh STDOUT:
352A
353err [] status=1 []
354B
355err [] status=1 [0 0]
356err [] status=1 [0 1]
357err [] status=1 [0 1 0]
358ok
359## END
360
361## N-I ash STDOUT:
362## END
363
364#### error in trap ERR (recursive)
365case $SH in dash) exit ;; esac
366
367err() {
368 echo err status $?
369 false
370 ( exit 2 ) # not recursively triggered
371 echo err 2
372}
373trap 'err' ERR
374
375echo A
376false
377echo B
378
379# Try it with errexit
380set -e
381false
382echo C
383
384## status: 1
385## STDOUT:
386A
387err status 1
388err 2
389B
390err status 1
391## END
392## N-I dash STDOUT:
393## END
394