1 |
## compare_shells: dash bash-4.4 mksh
|
2 |
|
3 |
# In this file:
|
4 |
#
|
5 |
# - strict_control-flow: break/continue at the top level should be fatal!
|
6 |
#
|
7 |
# Other tests:
|
8 |
# - spec/errexit-strict: command subs inherit errexit
|
9 |
# - TODO: does bash 4.4. use inherit_errexit?
|
10 |
#
|
11 |
# - spec/var-op-other tests strict_word-eval (negative indices and invalid
|
12 |
# utf-8)
|
13 |
# - hm I think these should be the default? compat-word-eval?
|
14 |
#
|
15 |
# - spec/arith tests strict_arith - invalid strings become 0
|
16 |
# - OSH has a warning that can turn into an error. I think the error could
|
17 |
# be the default (since this was a side effect of "ShellMathShock")
|
18 |
|
19 |
# - strict_array: unimplemented.
|
20 |
# - WAS undef[2]=x, but bash-completion relied on the associative array
|
21 |
# version of that.
|
22 |
# - TODO: It should disable decay_array EVERYWHERE except a specific case like:
|
23 |
# - s="${a[*]}" # quoted, the unquoted ones glob in a command context
|
24 |
# - spec/dbracket has array comparison relevant to the case below
|
25 |
#
|
26 |
# Most of those options could be compat-*.
|
27 |
#
|
28 |
# One that can't: strict_scope disables dynamic scope.
|
29 |
|
30 |
|
31 |
|
32 |
shopt -s strict_arith
|
33 |
## status: 0
|
34 |
## N-I bash status: 1
|
35 |
## N-I dash/mksh status: 127
|
36 |
|
37 |
|
38 |
echo one
|
39 |
. $REPO_ROOT/spec/testdata/return-helper.sh
|
40 |
echo $?
|
41 |
echo two
|
42 |
## STDOUT:
|
43 |
one
|
44 |
return-helper.sh
|
45 |
42
|
46 |
two
|
47 |
## END
|
48 |
|
49 |
|
50 |
$SH $REPO_ROOT/spec/testdata/top-level-control-flow.sh
|
51 |
## status: 0
|
52 |
## STDOUT:
|
53 |
SUBSHELL
|
54 |
BREAK
|
55 |
CONTINUE
|
56 |
RETURN
|
57 |
## OK bash STDOUT:
|
58 |
SUBSHELL
|
59 |
BREAK
|
60 |
CONTINUE
|
61 |
RETURN
|
62 |
DONE
|
63 |
## END
|
64 |
|
65 |
|
66 |
$SH -o errexit $REPO_ROOT/spec/testdata/top-level-control-flow.sh
|
67 |
## status: 2
|
68 |
## OK bash status: 1
|
69 |
## STDOUT:
|
70 |
SUBSHELL
|
71 |
## END
|
72 |
|
73 |
|
74 |
shopt -s strict_control_flow || true
|
75 |
echo break
|
76 |
break
|
77 |
echo hi
|
78 |
## STDOUT:
|
79 |
break
|
80 |
## END
|
81 |
## status: 1
|
82 |
## N-I dash/bash/mksh STDOUT:
|
83 |
break
|
84 |
hi
|
85 |
# END
|
86 |
## N-I dash/bash/mksh status: 0
|
87 |
|
88 |
|
89 |
return
|
90 |
echo "status=$?"
|
91 |
## stdout-json: ""
|
92 |
## OK bash STDOUT:
|
93 |
status=1
|
94 |
## END
|
95 |
|
96 |
|
97 |
# NOTE: bash and mksh both print warnings, but don't exit with an error.
|
98 |
continue
|
99 |
echo status=$?
|
100 |
## stdout: status=0
|
101 |
|
102 |
|
103 |
break
|
104 |
echo status=$?
|
105 |
## stdout: status=0
|
106 |
|
107 |
|
108 |
x=''
|
109 |
$x
|
110 |
echo status=$?
|
111 |
|
112 |
if $x; then
|
113 |
echo VarSub
|
114 |
fi
|
115 |
|
116 |
if $(echo foo >/dev/null); then
|
117 |
echo CommandSub
|
118 |
fi
|
119 |
|
120 |
if "$x"; then
|
121 |
echo VarSub
|
122 |
else
|
123 |
echo VarSub FAILED
|
124 |
fi
|
125 |
|
126 |
if "$(echo foo >/dev/null)"; then
|
127 |
echo CommandSub
|
128 |
else
|
129 |
echo CommandSub FAILED
|
130 |
fi
|
131 |
|
132 |
## STDOUT:
|
133 |
status=0
|
134 |
VarSub
|
135 |
CommandSub
|
136 |
VarSub FAILED
|
137 |
CommandSub FAILED
|
138 |
## END
|
139 |
|
140 |
|
141 |
shopt -s strict_argv || true
|
142 |
echo empty
|
143 |
x=''
|
144 |
$x
|
145 |
echo status=$?
|
146 |
## status: 1
|
147 |
## STDOUT:
|
148 |
empty
|
149 |
## END
|
150 |
## N-I dash/bash/mksh status: 0
|
151 |
## N-I dash/bash/mksh STDOUT:
|
152 |
empty
|
153 |
status=0
|
154 |
## END
|
155 |
|
156 |
|
157 |
|
158 |
# NOTE: from spec/dbracket has a test case like this
|
159 |
# sane-array should turn this ON.
|
160 |
# bash and mksh allow this because of decay
|
161 |
|
162 |
a=('a b' 'c d')
|
163 |
b=('a' 'b' 'c' 'd')
|
164 |
echo ${#a[@]}
|
165 |
echo ${#b[@]}
|
166 |
[[ "${a[@]}" == "${b[@]}" ]] && echo EQUAL
|
167 |
|
168 |
shopt -s strict_array || true
|
169 |
[[ "${a[@]}" == "${b[@]}" ]] && echo EQUAL
|
170 |
|
171 |
## status: 1
|
172 |
## STDOUT:
|
173 |
2
|
174 |
4
|
175 |
EQUAL
|
176 |
## END
|
177 |
## OK bash/mksh status: 0
|
178 |
## OK bash/mksh STDOUT:
|
179 |
2
|
180 |
4
|
181 |
EQUAL
|
182 |
EQUAL
|
183 |
## END
|
184 |
## N-I dash status: 2
|
185 |
## N-I dash stdout-json: ""
|
186 |
|
187 |
|
188 |
undef[2]=x
|
189 |
undef[3]=y
|
190 |
argv.py "${undef[@]}"
|
191 |
## STDOUT:
|
192 |
['x', 'y']
|
193 |
## END
|
194 |
## N-I dash status: 2
|
195 |
## N-I dash stdout-json: ""
|
196 |
|
197 |
|
198 |
shopt -u strict_arith || true
|
199 |
|
200 |
undef[2]=x
|
201 |
undef[3]=y
|
202 |
x='bad'
|
203 |
# bad gets coerced to zero, but this is part of the RECURSIVE arithmetic
|
204 |
# behavior, which we want to disallow. Consider disallowing in OSH.
|
205 |
|
206 |
undef[$x]=zzz
|
207 |
argv.py "${undef[@]}"
|
208 |
## STDOUT:
|
209 |
['zzz', 'x', 'y']
|
210 |
## END
|
211 |
## N-I dash status: 2
|
212 |
## N-I dash stdout-json: ""
|
213 |
|
214 |
|
215 |
for i in 1 2; do
|
216 |
eval # zero args
|
217 |
echo status=$?
|
218 |
eval echo one
|
219 |
echo status=$?
|
220 |
eval 'echo two'
|
221 |
echo status=$?
|
222 |
shopt -s simple_eval_builtin
|
223 |
echo ---
|
224 |
done
|
225 |
## STDOUT:
|
226 |
status=0
|
227 |
one
|
228 |
status=0
|
229 |
two
|
230 |
status=0
|
231 |
---
|
232 |
status=2
|
233 |
status=2
|
234 |
two
|
235 |
status=0
|
236 |
---
|
237 |
## END
|
238 |
## N-I dash/bash/mksh STDOUT:
|
239 |
status=0
|
240 |
one
|
241 |
status=0
|
242 |
two
|
243 |
status=0
|
244 |
---
|
245 |
status=0
|
246 |
one
|
247 |
status=0
|
248 |
two
|
249 |
status=0
|
250 |
---
|
251 |
## END
|
252 |
|
253 |
|
254 |
|
255 |
case $SH in bash*|dash|mksh) exit ;; esac
|
256 |
|
257 |
$SH -c '
|
258 |
a=(1 2 3); echo /${a[@]::}/
|
259 |
'
|
260 |
echo status=$?
|
261 |
|
262 |
$SH -c '
|
263 |
shopt --set strict_parse_slice
|
264 |
|
265 |
a=(1 2 3); echo /${a[@]::}/
|
266 |
'
|
267 |
echo status=$?
|
268 |
|
269 |
## STDOUT:
|
270 |
//
|
271 |
status=0
|
272 |
status=2
|
273 |
## END
|
274 |
|
275 |
## N-I bash/dash/mksh STDOUT:
|
276 |
## END
|
277 |
|
278 |
|
279 |
|
280 |
case $SH in bash*|dash|mksh) exit ;; esac
|
281 |
|
282 |
shopt --set ysh:all
|
283 |
|
284 |
for x in a b c {
|
285 |
echo $x
|
286 |
if (x === 'a') {
|
287 |
break
|
288 |
}
|
289 |
}
|
290 |
|
291 |
echo ---
|
292 |
|
293 |
for keyword in break continue return exit {
|
294 |
try {
|
295 |
$[ENV.SH] -o ysh:all -c '
|
296 |
var k = $1
|
297 |
for x in a b c {
|
298 |
echo $x
|
299 |
if (x === "a") {
|
300 |
$k
|
301 |
}
|
302 |
}
|
303 |
' unused $keyword
|
304 |
}
|
305 |
echo code=$[_error.code]
|
306 |
echo '==='
|
307 |
}
|
308 |
|
309 |
## STDOUT:
|
310 |
a
|
311 |
---
|
312 |
a
|
313 |
code=1
|
314 |
===
|
315 |
a
|
316 |
code=1
|
317 |
===
|
318 |
a
|
319 |
code=1
|
320 |
===
|
321 |
a
|
322 |
code=1
|
323 |
===
|
324 |
## END
|
325 |
|
326 |
## N-I bash/dash/mksh STDOUT:
|
327 |
## END
|
328 |
|
329 |
|
330 |
|
331 |
shopt --set strict:all
|
332 |
|
333 |
# This differs from what it means in a process
|
334 |
FOO=bar eval 'echo FOO=$FOO'
|
335 |
echo FOO=$FOO
|
336 |
|
337 |
## status: 1
|
338 |
## STDOUT:
|
339 |
## END
|
340 |
|
341 |
## BUG bash status: 0
|
342 |
## BUG bash STDOUT:
|
343 |
FOO=bar
|
344 |
FOO=
|
345 |
## END
|
346 |
|
347 |
## N-I dash/mksh status: 0
|
348 |
## N-I dash/mksh STDOUT:
|
349 |
FOO=bar
|
350 |
FOO=bar
|
351 |
## END
|