1 #!/usr/bin/env bash
2 #
3 # Usage:
4 # ./errexit.test.sh <function name>
5
6 #### errexit aborts early
7 set -o errexit
8 false
9 echo done
10 ## stdout-json: ""
11 ## status: 1
12
13 #### errexit for nonexistent command
14 set -o errexit
15 nonexistent__ZZ
16 echo done
17 ## stdout-json: ""
18 ## status: 127
19
20 #### errexit aborts early on pipeline
21 set -o errexit
22 echo hi | grep nonexistent
23 echo two
24 ## stdout-json: ""
25 ## status: 1
26
27 #### errexit with { }
28 # This aborts because it's not part of an if statement.
29 set -o errexit
30 { echo one; false; echo two; }
31 ## stdout: one
32 ## status: 1
33
34 #### errexit with if and { }
35 set -o errexit
36 if { echo one; false; echo two; }; then
37 echo three
38 fi
39 echo four
40 ## status: 0
41 ## STDOUT:
42 one
43 two
44 three
45 four
46 ## END
47
48 #### errexit with ||
49 set -o errexit
50 echo hi | grep nonexistent || echo ok
51 ## stdout: ok
52 ## status: 0
53
54 #### errexit with &&
55 set -o errexit
56 echo ok && echo hi | grep nonexistent
57 ## stdout: ok
58 ## status: 1
59
60 #### errexit test && -- from gen-module-init
61 set -o errexit
62 test "$mod" = readline && echo "#endif"
63 echo status=$?
64 ## stdout: status=1
65
66 #### errexit test && and fail
67 set -o errexit
68 test -n X && false
69 echo status=$?
70 ## stdout-json: ""
71 ## status: 1
72
73 #### errexit and loop
74 set -o errexit
75 for x in 1 2 3; do
76 test $x = 2 && echo "hi $x"
77 done
78 ## stdout: hi 2
79 ## status: 1
80
81 #### errexit and brace group { }
82 set -o errexit
83 { test no = yes && echo hi; }
84 echo status=$?
85 ## stdout: status=1
86
87 #### errexit and time { }
88 set -o errexit
89 time false
90 echo status=$?
91 ## status: 1
92
93 #### errexit with !
94 set -o errexit
95 echo one
96 ! true
97 echo two
98 ! false
99 echo three
100 ## STDOUT:
101 one
102 two
103 three
104 ## END
105
106 #### errexit with ! and ;
107 # AST has extra Sentence nodes; there was a REGRESSION here.
108 set -o errexit; echo one; ! true; echo two; ! false; echo three
109 ## STDOUT:
110 one
111 two
112 three
113 ## END
114
115 #### errexit with while/until
116 set -o errexit
117 while false; do
118 echo ok
119 done
120 until false; do
121 echo ok # do this once then exit loop
122 break
123 done
124 ## stdout: ok
125 ## status: 0
126
127 #### errexit with (( ))
128 # from http://mywiki.wooledge.org/BashFAQ/105, this changed between verisons.
129 # ash says that 'i++' is not found, but it doesn't exit. I guess this is the
130 # subshell problem?
131 set -o errexit
132 i=0
133 (( i++ ))
134 echo done
135 ## stdout-json: ""
136 ## status: 1
137 ## N-I dash status: 127
138 ## N-I dash stdout-json: ""
139 ## BUG ash status: 0
140 ## BUG ash stdout: done
141
142 #### errexit with subshell
143 set -o errexit
144 ( echo one; false; echo two; )
145 echo three
146 ## status: 1
147 ## STDOUT:
148 one
149 ## BUG ash status: 0
150 ## BUG ash STDOUT:
151 one
152 three
153 ## END
154
155 #### set -o errexit while it's being ignored
156 # ignored and then set again
157 set -o errexit
158 # osh aborts early here
159 if { echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; }; then
160 echo 5;
161 fi
162 echo 6
163 false # this is the one that makes other shells fail
164 echo 7
165 ## status: 1
166 ## STDOUT:
167 1
168 2
169 ## END
170 ## OK dash/bash/mksh/ash STDOUT:
171 1
172 2
173 3
174 4
175 5
176 6
177 ## END
178
179 #### set +o errexit while it's being ignored
180 # ignored and then set again
181 set -o errexit
182 # osh aborts early here
183 if { echo 1; false; echo 2; set +o errexit; echo 3; false; echo 4; }; then
184 echo 5;
185 fi
186 echo 6
187 ## status: 1
188 ## STDOUT:
189 1
190 2
191 ## END
192 ## OK dash/bash/mksh/ash status: 0
193 ## OK dash/bash/mksh/ash STDOUT:
194 1
195 2
196 3
197 4
198 5
199 6
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; )
204 echo 5
205 false
206 echo 6
207 ## STDOUT:
208 1
209 2
210 3
211 5
212 6
213 ## END
214
215 #### setting errexit while it's being ignored in a subshell
216 set -o errexit
217 if ( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4 ); then
218 echo 5;
219 fi
220 echo 6 # This is executed because the subshell just returns false
221 false
222 echo 7
223 ## status: 1
224 ## STDOUT:
225 1
226 2
227 6
228 ## OK dash/bash/mksh/ash STDOUT:
229 1
230 2
231 3
232 4
233 5
234 6
235 ## END
236
237 #### errexit double guard
238 # OSH bug fix. ErrExit needs a counter, not a boolean.
239 set -o errexit
240 if { ! false; false; true; } then
241 echo true
242 fi
243 false
244 echo done
245 ## status: 1
246 ## STDOUT:
247 true
248 ## END
249
250 #### background processes respect errexit
251 set -o errexit
252 { echo one; false; echo two; exit 42; } &
253 wait $!
254 ## status: 1
255 ## STDOUT:
256 one
257 ## END
258
259 #### pipeline process respects errexit
260 set -o errexit
261 # It is respected here.
262 { echo one; false; echo two; } | cat
263
264 # Also respected here.
265 { echo three; echo four; } | while read line; do
266 echo "[$line]"
267 false
268 done
269 echo four
270 ## status: 1
271 ## STDOUT:
272 one
273 [three]
274 ## END