1 ## compare_shells: bash dash mksh zsh
2 ## oils_failures_allowed: 0
3
4 #### can continue after unknown option
5 #
6 # TODO: this is the posix special builtin logic?
7 # dash and mksh make this a fatal error no matter what.
8
9 set -o errexit
10 set -o STRICT || true # unknown option
11 echo hello
12 ## stdout: hello
13 ## status: 0
14 ## BUG dash/mksh/zsh stdout-json: ""
15 ## BUG dash status: 2
16 ## BUG mksh/zsh status: 1
17
18 #### set with both options and argv
19 set -o errexit a b c
20 echo "$@"
21 false
22 echo done
23 ## stdout: a b c
24 ## status: 1
25
26 #### nounset with "$@"
27 set a b c
28 set -u # shouldn't touch argv
29 echo "$@"
30 ## stdout: a b c
31
32 #### set -u -- clears argv
33 set a b c
34 set -u -- # shouldn't touch argv
35 echo "$@"
36 ## stdout:
37
38 #### set -u -- x y z
39 set a b c
40 set -u -- x y z
41 echo "$@"
42 ## stdout: x y z
43
44 #### set -u with undefined variable exits the interpreter
45
46 # non-interactive
47 $SH -c 'set -u; echo before; echo $x; echo after'
48 if test $? -ne 0; then
49 echo OK
50 fi
51
52 # interactive
53 $SH -i -c 'set -u; echo before; echo $x; echo after'
54 if test $? -ne 0; then
55 echo OK
56 fi
57
58 ## STDOUT:
59 before
60 OK
61 before
62 OK
63 ## END
64
65 #### set -u with undefined var in interactive shell does NOT exit the interpreter
66
67 # In bash, it aborts the LINE only. The next line is executed!
68
69 # non-interactive
70 $SH -c 'set -u; echo before; echo $x; echo after
71 echo line2
72 '
73 if test $? -ne 0; then
74 echo OK
75 fi
76
77 # interactive
78 $SH -i -c 'set -u; echo before; echo $x; echo after
79 echo line2
80 '
81 if test $? -ne 0; then
82 echo OK
83 fi
84
85 ## STDOUT:
86 before
87 OK
88 before
89 line2
90 ## END
91
92 ## BUG dash/mksh/zsh STDOUT:
93 before
94 OK
95 before
96 OK
97 ## END
98
99 #### set -u error can break out of nested evals
100 $SH -c '
101 set -u
102 test_function_2() {
103 x=$blarg
104 }
105 test_function() {
106 eval "test_function_2"
107 }
108
109 echo before
110 eval test_function
111 echo after
112 '
113 # status must be non-zero: bash uses 1, ash/dash exit 2
114 if test $? -ne 0; then
115 echo OK
116 fi
117
118 ## STDOUT:
119 before
120 OK
121 ## END
122 ## BUG zsh/mksh STDOUT:
123 before
124 after
125 ## END
126
127 #### reset option with long flag
128 set -o errexit
129 set +o errexit
130 echo "[$unset]"
131 ## stdout: []
132 ## status: 0
133
134 #### reset option with short flag
135 set -u
136 set +u
137 echo "[$unset]"
138 ## stdout: []
139 ## status: 0
140
141 #### set -eu (flag parsing)
142 set -eu
143 echo "[$unset]"
144 echo status=$?
145 ## stdout-json: ""
146 ## status: 1
147 ## OK dash status: 2
148
149 #### set -o lists options
150 # NOTE: osh doesn't use the same format yet.
151 set -o | grep -o noexec
152 ## STDOUT:
153 noexec
154 ## END
155
156 #### 'set' and 'eval' round trip
157
158 # NOTE: not testing arrays and associative arrays!
159 _space='[ ]'
160 _whitespace=$'[\t\r\n]'
161 _sq="'single quotes'"
162 _backslash_dq="\\ \""
163 _unicode=$'[\u03bc]'
164
165 # Save the variables
166 varfile=$TMP/vars-$(basename $SH).txt
167
168 set | grep '^_' > "$varfile"
169
170 # Unset variables
171 unset _space _whitespace _sq _backslash_dq _unicode
172 echo [ $_space $_whitespace $_sq $_backslash_dq $_unicode ]
173
174 # Restore them
175
176 . $varfile
177 echo "Code saved to $varfile" 1>&2 # for debugging
178
179 test "$_space" = '[ ]' && echo OK
180 test "$_whitespace" = $'[\t\r\n]' && echo OK
181 test "$_sq" = "'single quotes'" && echo OK
182 test "$_backslash_dq" = "\\ \"" && echo OK
183 test "$_unicode" = $'[\u03bc]' && echo OK
184
185 ## STDOUT:
186 [ ]
187 OK
188 OK
189 OK
190 OK
191 OK
192 ## END
193
194 ## BUG zsh status: 1
195 ## BUG zsh STDOUT:
196 [ ]
197 ## END
198
199 #### set - - and so forth
200 set a b
201 echo "$@"
202
203 set - a b
204 echo "$@"
205
206 set -- a b
207 echo "$@"
208
209 set - -
210 echo "$@"
211
212 set -- --
213 echo "$@"
214
215 # note: zsh is different, and yash is totally different
216 ## STDOUT:
217 a b
218 a b
219 a b
220 -
221 --
222 ## END
223 ## N-I yash STDOUT:
224 a b
225 - a b
226 a b
227 - -
228 --
229 ## END
230 ## BUG zsh STDOUT:
231 a b
232 a b
233 a b
234
235 --
236 ## END
237
238 #### set - leading single dash is ignored, turns off xtrace verbose (#2364)
239
240 show_options() {
241 case $- in
242 *v*) echo verbose-on ;;
243 esac
244 case $- in
245 *x*) echo xtrace-on ;;
246 esac
247 }
248
249 set -x -v
250 show_options
251 echo
252
253 set - a b c
254 echo "$@"
255 show_options
256 echo
257
258 # dash that's not leading is not special
259 set x - y z
260 echo "$@"
261
262 ## STDOUT:
263 verbose-on
264 xtrace-on
265
266 a b c
267
268 x - y z
269 ## END
270
271 ## BUG zsh STDOUT:
272 verbose-on
273 xtrace-on
274
275 a b c
276 verbose-on
277 xtrace-on
278
279 x - y z
280 ## END
281
282 #### set - stops option processing like set --
283 case $SH in zsh) exit ;; esac
284
285 show_options() {
286 case $- in
287 *v*) echo verbose-on ;;
288 esac
289 case $- in
290 *x*) echo xtrace-on ;;
291 esac
292 }
293
294 set -x - -v
295
296 show_options
297 echo argv "$@"
298
299 ## STDOUT:
300 argv -v
301 ## END
302
303 ## N-I zsh STDOUT:
304 ## END
305
306 #### A single + is an ignored flag; not an argument
307 case $SH in zsh) exit ;; esac
308
309 show_options() {
310 case $- in
311 *v*) echo verbose-on ;;
312 esac
313 case $- in
314 *x*) echo xtrace-on ;;
315 esac
316 }
317
318 set +
319 echo plus "$@"
320
321 set -x + -v x y
322 show_options
323 echo plus "$@"
324
325 ## STDOUT:
326 plus
327 verbose-on
328 xtrace-on
329 plus x y
330 ## END
331
332 ## BUG mksh STDOUT:
333 plus
334 xtrace-on
335 plus -v x y
336 ## END
337
338 ## N-I zsh STDOUT:
339 ## END
340
341 #### set - + and + -
342 set - +
343 echo "$@"
344
345 set + -
346 echo "$@"
347
348 ## STDOUT:
349 +
350 +
351 ## END
352
353 ## BUG mksh STDOUT:
354 +
355 -
356 ## END
357
358 ## OK zsh/osh STDOUT:
359 +
360
361 ## END
362
363 #### set -a exports variables
364 set -a
365 FOO=bar
366 BAZ=qux
367 printenv.py FOO BAZ
368 ## STDOUT:
369 bar
370 qux
371 ## END
372
373 #### set +a stops exporting
374 set -a
375 FOO=exported
376 set +a
377 BAR=not_exported
378 printenv.py FOO BAR
379 ## STDOUT:
380 exported
381 None
382 ## END
383
384 #### set -o allexport (long form)
385 set -o allexport
386 VAR1=value1
387 set +o allexport
388 VAR2=value2
389 printenv.py VAR1 VAR2
390 ## STDOUT:
391 value1
392 None
393 ## END
394
395 #### variables set before set -a are not exported
396 BEFORE=before_value
397 set -a
398 AFTER=after_value
399 printenv.py BEFORE AFTER
400 ## STDOUT:
401 None
402 after_value
403 ## END
404
405 #### set -a exports local variables
406 set -a
407 f() {
408 local ZZZ=zzz
409 printenv.py ZZZ
410 }
411 f
412 ## STDOUT:
413 zzz
414 ## END
415 ## BUG mksh stdout: None
416
417 #### set -a exports declare variables
418 set -a
419 declare ZZZ=zzz
420 printenv.py ZZZ
421 ## STDOUT:
422 zzz
423 ## END
424 ## N-I dash/mksh stdout: None