1 ## compare_shells: bash dash mksh zsh ash
2 ## oils_failures_allowed: 0
3 ## oils_cpp_failures_allowed: 1
4 # TODO: fix C++ failure
5
6 #### echo keyword
7 echo done
8 ## stdout: done
9
10 #### if/else
11 if false; then
12 echo THEN
13 else
14 echo ELSE
15 fi
16 ## stdout: ELSE
17
18 #### Turn an array into an integer.
19 a=(1 2 3)
20 (( a = 42 ))
21 echo $a
22 ## stdout: 42
23 ## N-I dash/ash stdout-json: ""
24 ## N-I dash/ash status: 2
25
26
27 #### assign readonly -- one line
28 readonly x=1; x=2; echo hi
29 ## status: 1
30 ## OK dash/mksh/ash status: 2
31 ## STDOUT:
32 ## END
33
34 #### assign readonly -- multiple lines
35 readonly x=1
36 x=2
37 echo hi
38 ## status: 1
39 ## OK dash/mksh/ash status: 2
40 ## STDOUT:
41 ## END
42 ## BUG bash status: 0
43 ## BUG bash STDOUT:
44 hi
45 ## END
46
47 #### assign readonly -- multiple lines -- set -o posix
48 set -o posix
49 readonly x=1
50 x=2
51 echo hi
52 ## status: 1
53 ## OK dash/mksh/ash status: 2
54 ## STDOUT:
55 ## END
56
57 #### unset readonly -- one line
58 readonly x=1; unset x; echo hi
59 ## STDOUT:
60 hi
61 ## END
62 ## OK dash/ash status: 2
63 ## OK zsh status: 1
64 ## OK dash/ash stdout-json: ""
65 ## OK zsh stdout-json: ""
66
67 #### unset readonly -- multiple lines
68 readonly x=1
69 unset x
70 echo hi
71 ## OK dash/ash status: 2
72 ## OK zsh status: 1
73 ## OK dash/ash stdout-json: ""
74 ## OK zsh stdout-json: ""
75
76 #### First word like foo$x() and foo$[1+2] (regression)
77
78 # Problem: $x() func call broke this error message
79 foo$identity('z')
80
81 foo$[1+2]
82
83 echo DONE
84
85 ## status: 2
86 ## OK mksh/zsh status: 1
87 ## STDOUT:
88 ## END
89
90 #### Function names
91 foo$x() {
92 echo hi
93 }
94
95 foo $x() {
96 echo hi
97 }
98
99 ## status: 2
100 ## OK mksh/zsh status: 1
101 ## BUG zsh status: 0
102 ## STDOUT:
103 ## END
104
105
106 #### file with NUL byte
107 echo -e 'echo one \0 echo two' > tmp.sh
108 $SH tmp.sh
109 ## STDOUT:
110 one echo two
111 ## END
112 ## OK osh STDOUT:
113 one
114 ## END
115 ## N-I dash stdout-json: ""
116 ## N-I dash status: 127
117 ## OK bash stdout-json: ""
118 ## OK bash status: 126
119 ## OK zsh stdout-json: "one \u0000echo two\n"
120
121 #### fastlex: PS1 format string that's incomplete / with NUL byte
122 case $SH in bash) exit ;; esac
123
124 x=$'\\D{%H:%M' # leave off trailing }
125 echo x=${x@P}
126
127 ## STDOUT:
128 x=\D{%H:%M
129 ## END
130
131 # bash just ignores the missing }
132 ## BUG bash stdout-json: ""
133
134 # These shells don't understand @P
135
136 ## N-I dash/ash stdout-json: ""
137 ## N-I dash/ash status: 2
138
139 ## N-I zsh stdout-json: ""
140 ## N-I zsh status: 1
141
142
143 #### 'echo' and printf fail on writing to full disk
144
145 # Inspired by https://blog.sunfishcode.online/bugs-in-hello-world/
146
147 echo hi > /dev/full
148 echo status=$?
149
150 printf '%s\n' hi > /dev/full
151 echo status=$?
152
153 ## STDOUT:
154 status=1
155 status=1
156 ## END
157
158 #### other builtins fail on writing to full disk
159
160 type echo > /dev/full
161 echo status=$?
162
163 # other random builtin
164 ulimit -a > /dev/full
165 echo status=$?
166
167 ## STDOUT:
168 status=1
169 status=1
170 ## END
171
172 ## BUG mksh/zsh STDOUT:
173 status=0
174 status=0
175 ## END
176
177 #### subshell while running a script (regression)
178 # Ensures that spawning a subshell doesn't cause a seek on the file input stream
179 # representing the current script (issue #1233).
180 cat >tmp.sh <<'EOF'
181 echo start
182 (:)
183 echo end
184 EOF
185 $SH tmp.sh
186 ## STDOUT:
187 start
188 end
189 ## END
190
191 #### for loop (issue #1446)
192 case $SH in (dash|mksh|ash) exit ;; esac
193
194 for (( n=0; n<(3-(1)); n++ )) ; do echo $n; done
195
196 ## STDOUT:
197 0
198 1
199 ## END
200 ## N-I dash/mksh/ash STDOUT:
201 ## END
202
203
204
205 #### for loop 2 (issue #1446)
206 case $SH in (dash|mksh|ash) exit ;; esac
207
208
209 for (( n=0; n<(3- (1)); n++ )) ; do echo $n; done
210
211 ## STDOUT:
212 0
213 1
214 ## END
215 ## N-I dash/mksh/ash STDOUT:
216 ## END
217
218 #### autoconf word split (#1449)
219
220 mysed() {
221 for line in "$@"; do
222 echo "[$line]"
223 done
224 }
225
226 sedinputs="f1 f2"
227 sedscript='my sed command'
228
229 # Parsed and evaluated correctly: with word_part.EscapedLiteral \"
230
231 x=$(eval "mysed -n \"\$sedscript\" $sedinputs")
232 echo '--- $()'
233 echo "$x"
234
235 # With backticks, the \" gets lost somehow
236
237 x=`eval "mysed -n \"\$sedscript\" $sedinputs"`
238 echo '--- backticks'
239 echo "$x"
240
241
242 # Test it in a case statement
243
244 case `eval "mysed -n \"\$sedscript\" $sedinputs"` in
245 (*'[my sed command]'*)
246 echo 'NOT SPLIT'
247 ;;
248 esac
249
250 ## STDOUT:
251 --- $()
252 [-n]
253 [my sed command]
254 [f1]
255 [f2]
256 --- backticks
257 [-n]
258 [my sed command]
259 [f1]
260 [f2]
261 NOT SPLIT
262 ## END
263
264 #### autoconf arithmetic - relaxed eval_unsafe_arith (#1450)
265
266 as_fn_arith ()
267 {
268 as_val=$(( $* ))
269 }
270 as_fn_arith 1 + 1
271 echo $as_val
272
273 ## STDOUT:
274 2
275 ## END
276
277 #### command execution $(echo 42 | tee PWNED) not allowed
278
279 rm -f PWNED
280
281 x='a[$(echo 42 | tee PWNED)]=1'
282 echo $(( x ))
283
284 if test -f PWNED; then
285 cat PWNED
286 else
287 echo NOPE
288 fi
289
290 ## status: 1
291 ## OK dash/ash status: 2
292 ## stdout-json: ""
293 ## BUG bash/mksh/zsh status: 0
294 ## BUG bash/mksh/zsh STDOUT:
295 1
296 42
297 ## END
298
299 #### process sub <(echo 42 | tee PWNED) not allowed
300
301 rm -f PWNED
302
303 x='a[<(echo 42 | tee PWNED)]=1'
304 echo $(( x ))
305
306 if test -f PWNED; then
307 cat PWNED
308 else
309 echo NOPE
310 fi
311
312 ## status: 1
313 ## stdout-json: ""
314
315 ## OK dash/ash status: 2
316
317 # bash keeps going
318 ## BUG bash status: 0
319 ## BUG bash STDOUT:
320 NOPE
321 ## END
322
323
324 #### unset doesn't allow command execution
325
326 typeset -a a # for mksh
327 a=(42)
328 echo len=${#a[@]}
329
330 unset -v 'a[$(echo 0 | tee PWNED)]'
331 echo len=${#a[@]}
332
333 if test -f PWNED; then
334 echo PWNED
335 cat PWNED
336 else
337 echo NOPE
338 fi
339
340 ## status: 1
341 ## STDOUT:
342 len=1
343 ## END
344
345 ## N-I dash/ash status: 2
346 ## N-I dash/ash stdout-json: ""
347
348 ## BUG bash/mksh status: 0
349 ## BUG bash/mksh STDOUT:
350 len=1
351 len=0
352 PWNED
353 0
354 ## END
355
356 ## BUG zsh status: 0
357 ## BUG zsh STDOUT:
358 len=1
359 len=1
360 PWNED
361 0
362 ## END
363
364 #### printf integer size bug
365
366 # from Koiche on Zulip
367
368 printf '%x\n' 2147483648
369 printf '%u\n' 2147483648
370 ## STDOUT:
371 80000000
372 2147483648
373 ## END
374
375 #### (( status bug
376
377 # from Koiche on Zulip
378
379 case $SH in dash|ash) exit ;; esac
380
381 (( 1 << 32 ))
382 echo status=$?
383
384 (( 1 << 32 )) && echo yes
385
386 ## STDOUT:
387 status=0
388 yes
389 ## END
390
391 ## N-I dash/ash STDOUT:
392 ## END
393
394 #### autotools as_fn_arith bug in configure
395
396 # Causes 'grep -e' check to infinite loop.
397 # Reduced from a configure script.
398
399 as_fn_arith() {
400 as_val=$(( $* ))
401 }
402
403 as_fn_arith 0 + 1
404 echo as_val=$as_val
405 ## STDOUT:
406 as_val=1
407 ## END
408
409 #### osh-native duplicates stdin - is this a test harness issue?
410
411 echo $0 | grep -o sh
412
413 ## STDOUT:
414 sh
415 ## END