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