OILS / spec / ble-idioms.test.sh View on Github | oils.pub

574 lines, 279 significant
1## compare_shells: bash zsh mksh ash
2## oils_failures_allowed: 5
3
4#### recursive arith: one level
5a='b=123'
6echo $((a))
7## stdout: 123
8## N-I dash status: 2
9## N-I dash stdout-json: ""
10## N-I yash stdout: b=123
11
12#### recursive arith: two levels
13a='b=c' c='d=123'
14echo $((a))
15## stdout: 123
16## N-I dash status: 2
17## N-I dash stdout-json: ""
18## N-I yash stdout: b=c
19
20#### recursive arith: short circuit &&, ||
21# Note: mksh R52 has a bug. Even though it supports a short circuit like
22# "echo $((cond&&(a=1)))", it doesn't work with "x=a=1; echo
23# $((cond&&x))". It is fixed at least in mksh R57.
24# Note: "busybox sh" doesn't support short circuit.
25a=b=123
26echo $((1||a)):$((b))
27echo $((0||a)):$((b))
28c=d=321
29echo $((0&&c)):$((d))
30echo $((1&&c)):$((d))
31## STDOUT:
321:0
331:123
340:0
351:321
36## END
37
38## BUG mksh/ash STDOUT:
391:123
401:123
410:321
421:321
43## END
44
45## N-I dash/yash status: 2
46## N-I dash/yash STDOUT:
471:0
48## END
49
50#### recursive arith: short circuit ?:
51# Note: "busybox sh" behaves strangely.
52y=a=123 n=a=321
53echo $((1?(y):(n))):$((a))
54echo $((0?(y):(n))):$((a))
55## STDOUT:
56123:123
57321:321
58## END
59## BUG ash STDOUT:
60123:321
61321:321
62## END
63## N-I dash status: 2
64## N-I dash stdout-json: ""
65## N-I yash STDOUT:
66a=123:0
67a=321:0
68## END
69
70#### recursive arith: side effects
71# In Zsh and Busybox sh, the side effect of inner arithmetic
72# evaluations seems to take effect only after the whole evaluation.
73a='b=c' c='d=123'
74echo $((a,d)):$((d))
75## stdout: 123:123
76## BUG zsh/ash stdout: 0:123
77## N-I dash/yash status: 2
78## N-I dash/yash stdout-json: ""
79
80#### recursive arith: recursion
81loop='i<=100&&(s+=i,i++,loop)' s=0 i=0
82echo $((a=loop,s))
83## stdout: 5050
84## N-I mksh status: 1
85## N-I mksh stdout-json: ""
86## N-I ash/dash/yash status: 2
87## N-I ash/dash/yash stdout-json: ""
88
89#### recursive arith: array elements
90text[1]='d=123'
91text[2]='text[1]'
92text[3]='text[2]'
93echo $((a=text[3]))
94## stdout: 123
95## N-I ash/dash/yash status: 2
96## N-I ash/dash/yash stdout-json: ""
97
98#### dynamic arith varname: assign
99vec2_set () {
100 local this=$1 x=$2 y=$3
101 : $(( ${this}_x = $2 ))
102 : $(( ${this}_y = y ))
103}
104vec2_set a 3 4
105vec2_set b 5 12
106echo a_x=$a_x a_y=$a_y
107echo b_x=$b_x b_y=$b_y
108## STDOUT:
109a_x=3 a_y=4
110b_x=5 b_y=12
111## END
112
113#### dynamic arith varname: read
114
115vec2_load() {
116 local this=$1
117 x=$(( ${this}_x ))
118 : $(( y = ${this}_y ))
119}
120a_x=12 a_y=34
121vec2_load a
122echo x=$x y=$y
123## STDOUT:
124x=12 y=34
125## END
126
127#### dynamic arith varname: copy/add
128shopt -s eval_unsafe_arith # for RHS
129
130vec2_copy () {
131 local this=$1 rhs=$2
132 : $(( ${this}_x = $(( ${rhs}_x )) ))
133 : $(( ${this}_y = ${rhs}_y ))
134}
135vec2_add () {
136 local this=$1 rhs=$2
137 : $(( ${this}_x += $(( ${rhs}_x )) ))
138 : $(( ${this}_y += ${rhs}_y ))
139}
140a_x=3 a_y=4
141b_x=4 b_y=20
142vec2_copy c a
143echo c_x=$c_x c_y=$c_y
144vec2_add c b
145echo c_x=$c_x c_y=$c_y
146## STDOUT:
147c_x=3 c_y=4
148c_x=7 c_y=24
149## END
150
151#### is-array with ${var@a}
152case $SH in mksh|ash|dash|yash) exit 1 ;; esac
153
154function ble/is-array { [[ ${!1@a} == *a* ]]; }
155
156ble/is-array undef
157echo undef $?
158
159string=''
160ble/is-array string
161echo string $?
162
163array=(one two three)
164ble/is-array array
165echo array $?
166## STDOUT:
167undef 1
168string 1
169array 0
170## END
171## N-I zsh/mksh/ash/dash/yash status: 1
172## N-I zsh/mksh/ash/dash/yash stdout-json: ""
173
174
175#### Sparse array with big index
176
177# TODO: more InternalStringArray idioms / stress tests ?
178
179a=()
180
181if false; then
182 # This takes too long! # From Zulip
183 i=$(( 0x0100000000000000 ))
184else
185 # smaller number that's OK
186 i=$(( 0x0100000 ))
187fi
188
189a[i]=1
190
191echo len=${#a[@]}
192
193## STDOUT:
194len=1
195## END
196
197## N-I ash/dash status: 2
198## N-I ash/dash STDOUT:
199## END
200## N-I yash STDOUT:
201len=
202## END
203
204## BUG zsh STDOUT:
205len=1048576
206## END
207
208
209#### shift unshift reverse
210
211case $SH in mksh|ash) exit ;; esac
212
213# https://github.com/akinomyoga/ble.sh/blob/79beebd928cf9f6506a687d395fd450d027dc4cd/src/util.sh#L578-L582
214
215# @fn ble/array#unshift arr value...
216function ble/array#unshift {
217 builtin eval -- "$1=(\"\${@:2}\" \"\${$1[@]}\")"
218}
219# @fn ble/array#shift arr count
220function ble/array#shift {
221 # Note: Bash 4.3 以下では ${arr[@]:${2:-1}} が offset='${2'
222 # length='-1' に解釈されるので、先に算術式展開させる。
223 builtin eval -- "$1=(\"\${$1[@]:$((${2:-1}))}\")"
224}
225# @fn ble/array#reverse arr
226function ble/array#reverse {
227 builtin eval "
228 set -- \"\${$1[@]}\"; $1=()
229 local e$1 i$1=\$#
230 for e$1; do $1[--i$1]=\"\$e$1\"; done"
231}
232
233a=( {1..6} )
234echo "${a[@]}"
235
236ble/array#shift a 1
237echo "${a[@]}"
238
239ble/array#shift a 2
240echo "${a[@]}"
241
242echo ---
243
244ble/array#unshift a 99
245echo "${a[@]}"
246
247echo ---
248
249# doesn't work in zsh!
250ble/array#reverse a
251echo "${a[@]}"
252
253
254## STDOUT:
2551 2 3 4 5 6
2562 3 4 5 6
2574 5 6
258---
25999 4 5 6
260---
2616 5 4 99
262## END
263
264## BUG zsh STDOUT:
2651 2 3 4 5 6
2662 3 4 5 6
2674 5 6
268---
26999 4 5 6
270---
2715 4 99
272## END
273
274## N-I dash status: 2
275## N-I mksh/ash/dash STDOUT:
276## END
277# Note: yash does not support calling function name with '#'
278## N-I yash STDOUT:
279{1..6}
280{1..6}
281{1..6}
282---
283{1..6}
284---
285{1..6}
286## END
287
288
289#### shopt -u expand_aliases and eval
290case $SH in zsh|mksh|ash|dash|yash) exit ;; esac
291
292alias echo=false
293
294function f {
295 shopt -u expand_aliases
296 eval -- "$1"
297 shopt -s expand_aliases
298}
299
300f 'echo hello'
301
302## STDOUT:
303hello
304## END
305## N-I zsh/mksh/ash/dash/yash STDOUT:
306## END
307
308
309#### Issue #1069 [40] BUG: a=(declare v); "${a[@]}" fails
310case $SH in ash|dash) exit 99 ;; esac
311a=(typeset v=1)
312v=x
313"${a[@]}"
314echo "v=$v"
315## STDOUT:
316v=1
317## END
318# Note: ash/dash does not have arrays
319## N-I ash/dash status: 99
320## N-I ash/dash stdout-json: ""
321
322
323#### Issue #1069 [40] BUG: a=declare; "$a" v=1 fails
324case $SH in ash|dash) exit 99 ;; esac
325a=typeset
326v=x
327"$a" v=1
328echo "v=$v"
329## STDOUT:
330v=1
331## END
332## N-I ash/dash status: 99
333## N-I ash/dash stdout-json: ""
334
335
336#### Issue #1069 [49] BUG: \return 0 does not work
337f0() { return 3; echo unexpected; return 0; }
338f1() { \return 3; echo unexpected; return 0; }
339f0; echo "status=$?"
340f1; echo "status=$?"
341## STDOUT:
342status=3
343status=3
344## END
345
346
347#### Issue #1069 [49] BUG: \return 0 does not work (other variations)
348f2() { builtin return 3; echo unexpected; return 0; }
349f3() { \builtin return 3; echo unexpected; return 0; }
350f4() { command return 3; echo unexpected; return 0; }
351f2; echo "status=$?"
352f3; echo "status=$?"
353f4; echo "status=$?"
354## STDOUT:
355status=3
356status=3
357status=3
358## END
359# Note: zsh does not allow calling builtin through command
360## OK zsh STDOUT:
361status=3
362status=3
363unexpected
364status=0
365## END
366# Note: ash does not have "builtin"
367## N-I ash/dash/yash STDOUT:
368unexpected
369status=0
370unexpected
371status=0
372status=3
373## END
374
375
376#### Issue #1069 [52] BUG: \builtin local v=1 fails
377case $SH in ash|dash|yash) exit 99 ;; esac
378v=x
379case $SH in
380mksh) f1() { \builtin typeset v=1; echo "l:v=$v"; } ;;
381*) f1() { \builtin local v=1; echo "l:v=$v"; } ;;
382esac
383f1
384echo "g:v=$v"
385## STDOUT:
386l:v=1
387g:v=x
388## END
389# Note: ash/dash/yash does not have "builtin"
390## N-I ash/dash/yash status: 99
391## N-I ash/dash/yash stdout-json: ""
392
393
394#### Issue #1069 [53] BUG: a[1 + 1]=2, etc. fails
395case $SH in ash|dash|yash) exit 99 ;; esac
396a=()
397
398a[1]=x
399eval 'a[5&3]=hello'
400echo "status=$?, a[1]=${a[1]}"
401
402a[2]=x
403eval 'a[1 + 1]=hello'
404echo "status=$?, a[2]=${a[2]}"
405
406a[3]=x
407eval 'a[1|2]=hello'
408echo "status=$?, a[3]=${a[3]}"
409## STDOUT:
410status=0, a[1]=hello
411status=0, a[2]=hello
412status=0, a[3]=hello
413## END
414## OK zsh STDOUT:
415status=1, a[1]=x
416status=1, a[2]=x
417status=1, a[3]=x
418## END
419# Note: ash/dash does not have arrays
420# Note: yash does not support a[index]=value
421## N-I ash/dash/yash status: 99
422## N-I ash/dash/yash stdout-json: ""
423
424
425#### Issue #1069 [53] - LHS array parsing a[1 + 2]=3 (see spec/array-assign for more)
426case $SH in zsh|ash) exit ;; esac
427
428a[1 + 2]=7
429a[3|4]=8
430a[(1+2)*3]=9
431
432typeset -p a
433
434# Dynamic parsing
435expr='1 + 2'
436a[expr]=55
437
438b=(42)
439expr='b[0]'
440a[3 + $expr - 4]=66
441
442typeset -p a
443
444## STDOUT:
445declare -a a=([3]="7" [7]="8" [9]="9")
446declare -a a=([3]="55" [7]="8" [9]="9" [41]="66")
447## END
448
449## OK mksh STDOUT:
450set -A a
451typeset a[3]=7
452typeset a[7]=8
453typeset a[9]=9
454set -A a
455typeset a[3]=55
456typeset a[7]=8
457typeset a[9]=9
458typeset a[41]=66
459## END
460
461## N-I zsh/ash STDOUT:
462## END
463
464
465#### Issue #1069 [56] BUG: declare -p unset does not print any error message
466typeset -p nonexistent
467## status: 1
468## STDERR:
469[ stdin ]:1: osh: typeset: 'nonexistent' is not defined
470## END
471## STDOUT:
472## END
473## OK bash STDERR:
474bash: line 1: typeset: nonexistent: not found
475## END
476## OK mksh status: 0
477## OK mksh STDERR:
478## END
479## OK zsh STDERR:
480typeset: no such variable: nonexistent
481## END
482## OK ash status: 127
483## OK ash STDERR:
484ash: typeset: not found
485## END
486## OK dash status: 127
487## OK dash STDERR:
488dash: 1: typeset: not found
489## END
490## OK yash STDERR:
491typeset: no such variable $nonexistent
492## END
493
494
495#### Issue #1069 [57] BUG: variable v is invisible after IFS= eval 'local v=...'
496v=x
497case $SH in
498mksh) f() { IFS= eval 'typeset v=1'; echo "l:$v"; } ;;
499*) f() { IFS= eval 'local v=1'; echo "l:$v"; } ;;
500esac
501f
502echo "g:$v"
503## STDOUT:
504l:1
505g:x
506## END
507
508
509#### Issue #1069 [57] - Variable v should be visible after IFS= eval 'local v=...'
510
511set -u
512
513f() {
514 # The temp env messes it up
515 IFS= eval "local v=\"\$*\""
516
517 # Bug does not appear with only eval
518 # eval "local v=\"\$*\""
519
520 #declare -p v
521 echo v=$v
522
523 # test -v v; echo "v defined $?"
524}
525
526f h e l l o
527
528## STDOUT:
529v=hello
530## END
531
532
533#### Issue #1069 [59] N-I: arr=s should set RHS to arr[0]
534case $SH in ash|dash) exit 99 ;; esac
535a=(1 2 3)
536a=v
537argv.py "${a[@]}"
538## STDOUT:
539['v', '2', '3']
540## END
541## N-I zsh/yash STDOUT:
542['v']
543## END
544# Note: ash/dash does not have arrays
545## N-I ash/dash status: 99
546## N-I ash/dash stdout-json: ""
547
548
549#### Issue #1069 [59] - Assigning Str to BashArray/BashAssoc should not remove BashArray/BashAssoc
550case $SH in zsh|ash) exit ;; esac
551
552a=(1 2 3)
553a=99
554typeset -p a
555
556typeset -A A=([k]=v)
557A=99
558typeset -p A
559
560## STDOUT:
561declare -a a=([0]="99" [1]="2" [2]="3")
562declare -A A=([0]="99" [k]="v" )
563## END
564
565## OK mksh status: 1
566## OK mksh STDOUT:
567set -A a
568typeset a[0]=99
569typeset a[1]=2
570typeset a[2]=3
571## END
572
573## N-I zsh/ash STDOUT:
574## END