OILS / spec / strict-options.test.sh View on Github | oils.pub

351 lines, 171 significant
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#### strict_arith option
32shopt -s strict_arith
33## status: 0
34## N-I bash status: 1
35## N-I dash/mksh status: 127
36
37#### Sourcing a script that returns at the top level
38echo one
39. $REPO_ROOT/spec/testdata/return-helper.sh
40echo $?
41echo two
42## STDOUT:
43one
44return-helper.sh
4542
46two
47## END
48
49#### top level control flow
50$SH $REPO_ROOT/spec/testdata/top-level-control-flow.sh
51## status: 0
52## STDOUT:
53SUBSHELL
54BREAK
55CONTINUE
56RETURN
57## OK bash STDOUT:
58SUBSHELL
59BREAK
60CONTINUE
61RETURN
62DONE
63## END
64
65#### errexit and top-level control flow
66$SH -o errexit $REPO_ROOT/spec/testdata/top-level-control-flow.sh
67## status: 2
68## OK bash status: 1
69## STDOUT:
70SUBSHELL
71## END
72
73#### shopt -s strict_control_flow
74shopt -s strict_control_flow || true
75echo break
76break
77echo hi
78## STDOUT:
79break
80## END
81## status: 1
82## N-I dash/bash/mksh STDOUT:
83break
84hi
85# END
86## N-I dash/bash/mksh status: 0
87
88#### return at top level is an error
89return
90echo "status=$?"
91## stdout-json: ""
92## OK bash STDOUT:
93status=1
94## END
95
96#### continue at top level is NOT an error
97# NOTE: bash and mksh both print warnings, but don't exit with an error.
98continue
99echo status=$?
100## stdout: status=0
101
102#### break at top level is NOT an error
103break
104echo status=$?
105## stdout: status=0
106
107#### empty argv WITHOUT strict_argv
108x=''
109$x
110echo status=$?
111
112if $x; then
113 echo VarSub
114fi
115
116if $(echo foo >/dev/null); then
117 echo CommandSub
118fi
119
120if "$x"; then
121 echo VarSub
122else
123 echo VarSub FAILED
124fi
125
126if "$(echo foo >/dev/null)"; then
127 echo CommandSub
128else
129 echo CommandSub FAILED
130fi
131
132## STDOUT:
133status=0
134VarSub
135CommandSub
136VarSub FAILED
137CommandSub FAILED
138## END
139
140#### empty argv WITH strict_argv
141shopt -s strict_argv || true
142echo empty
143x=''
144$x
145echo status=$?
146## status: 1
147## STDOUT:
148empty
149## END
150## N-I dash/bash/mksh status: 0
151## N-I dash/bash/mksh STDOUT:
152empty
153status=0
154## END
155
156#### Arrays are incorrectly compared, but strict_array prevents it
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
162a=('a b' 'c d')
163b=('a' 'b' 'c' 'd')
164echo ${#a[@]}
165echo ${#b[@]}
166[[ "${a[@]}" == "${b[@]}" ]] && echo EQUAL
167
168shopt -s strict_array || true
169[[ "${a[@]}" == "${b[@]}" ]] && echo EQUAL
170
171## status: 1
172## STDOUT:
1732
1744
175EQUAL
176## END
177## OK bash/mksh status: 0
178## OK bash/mksh STDOUT:
1792
1804
181EQUAL
182EQUAL
183## END
184## N-I dash status: 2
185## N-I dash stdout-json: ""
186
187#### automatically creating arrays WITHOUT strict_array
188undef[2]=x
189undef[3]=y
190argv.py "${undef[@]}"
191## STDOUT:
192['x', 'y']
193## END
194## N-I dash status: 2
195## N-I dash stdout-json: ""
196
197#### automatically creating arrays are INDEXED, not associative
198shopt -u strict_arith || true
199
200undef[2]=x
201undef[3]=y
202x='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
206undef[$x]=zzz
207argv.py "${undef[@]}"
208## STDOUT:
209['zzz', 'x', 'y']
210## END
211## N-I dash status: 2
212## N-I dash stdout-json: ""
213
214#### simple_eval_builtin
215for 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 ---
224done
225## STDOUT:
226status=0
227one
228status=0
229two
230status=0
231---
232status=2
233status=2
234two
235status=0
236---
237## END
238## N-I dash/bash/mksh STDOUT:
239status=0
240one
241status=0
242two
243status=0
244---
245status=0
246one
247status=0
248two
249status=0
250---
251## END
252
253
254#### strict_parse_slice means you need explicit length
255case $SH in bash*|dash|mksh) exit ;; esac
256
257$SH -c '
258a=(1 2 3); echo /${a[@]::}/
259'
260echo status=$?
261
262$SH -c '
263shopt --set strict_parse_slice
264
265a=(1 2 3); echo /${a[@]::}/
266'
267echo status=$?
268
269## STDOUT:
270//
271status=0
272status=2
273## END
274
275## N-I bash/dash/mksh STDOUT:
276## END
277
278
279#### Control flow must be static in YSH (strict_control_flow)
280case $SH in bash*|dash|mksh) exit ;; esac
281
282shopt --set ysh:all
283
284for x in a b c {
285 echo $x
286 if (x === 'a') {
287 break
288 }
289}
290
291echo ---
292
293for 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:
310a
311---
312a
313code=1
314===
315a
316code=1
317===
318a
319code=1
320===
321a
322code=1
323===
324## END
325
326## N-I bash/dash/mksh STDOUT:
327## END
328
329#### shopt -s strict_binding: Persistent prefix bindings not allowed on special builtins
330
331shopt --set strict:all
332
333# This differs from what it means in a process
334FOO=bar eval 'echo FOO=$FOO'
335echo FOO=$FOO
336
337## status: 1
338## STDOUT:
339## END
340
341## BUG bash status: 0
342## BUG bash STDOUT:
343FOO=bar
344FOO=
345## END
346
347## N-I dash/mksh status: 0
348## N-I dash/mksh STDOUT:
349FOO=bar
350FOO=bar
351## END