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 (moot with strict_errexit)
156 set -o errexit
157 # osh aborts early here
158 if { echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; }; then
159 echo 5;
160 fi
161 echo 6
162 false # this is the one that makes shells fail
163 echo 7
164 ## status: 1
165 ## STDOUT:
166 1
167 2
168 3
169 4
170 5
171 6
172 ## END
173
174 #### set +o errexit while it's being ignored (moot with strict_errexit)
175 set -o errexit
176 if { echo 1; false; echo 2; set +o errexit; echo 3; false; echo 4; }; then
177 echo 5;
178 fi
179 echo 6
180 false # does NOT fail, because we restored it.
181 echo 7
182 ## STDOUT:
183 1
184 2
185 3
186 4
187 5
188 6
189 7
190 ## END
191
192 #### setting errexit in a subshell works but doesn't affect parent shell
193 ( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4; )
194 echo 5
195 false
196 echo 6
197 ## STDOUT:
198 1
199 2
200 3
201 5
202 6
203 ## END
204
205 #### set errexit while it's ignored in a subshell (moot with strict_errexit)
206 set -o errexit
207 if ( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4 ); then
208 echo 5;
209 fi
210 echo 6 # This is executed because the subshell just returns false
211 false
212 echo 7
213 ## status: 1
214 ## STDOUT:
215 1
216 2
217 3
218 4
219 5
220 6
221 ## END
222
223 #### shopt -s strict:all || true while errexit is on
224 set -o errexit
225 shopt -s strict:all || true
226 echo one
227 false # fail
228 echo two
229 ## status: 1
230 ## STDOUT:
231 one
232 ## END
233
234 #### errexit double guard
235 # OSH bug fix. ErrExit needs a counter, not a boolean.
236 set -o errexit
237 if { ! false; false; true; } then
238 echo true
239 fi
240 false
241 echo done
242 ## status: 1
243 ## STDOUT:
244 true
245 ## END
246
247 #### background processes respect errexit
248 set -o errexit
249 { echo one; false; echo two; exit 42; } &
250 wait $!
251 ## status: 1
252 ## STDOUT:
253 one
254 ## END
255
256 #### pipeline process respects errexit
257 set -o errexit
258 # It is respected here.
259 { echo one; false; echo two; } | cat
260
261 # Also respected here.
262 { echo three; echo four; } | while read line; do
263 echo "[$line]"
264 false
265 done
266 echo four
267 ## status: 1
268 ## STDOUT:
269 one
270 [three]
271 ## END