OILS / spec / loop.test.sh View on Github | oils.pub

615 lines, 399 significant
1## compare_shells: dash bash mksh zsh
2## oils_failures_allowed: 0
3
4#### implicit for loop
5# This is like "for i in $@".
6fun() {
7 for i; do
8 echo $i
9 done
10 echo "finished=$i"
11}
12fun 1 2 3
13## STDOUT:
141
152
163
17finished=3
18## END
19
20#### empty for loop (has "in")
21set -- 1 2 3
22for i in ; do
23 echo $i
24done
25## STDOUT:
26## END
27
28#### for loop with invalid identifier
29# should be compile time error, but runtime error is OK too
30for - in a b c; do
31 echo hi
32done
33## stdout-json: ""
34## status: 2
35## OK bash/mksh status: 1
36## BUG zsh stdout: hi
37## BUG zsh status: 1
38
39#### the word 'in' can be the loop variable
40
41for in in a b c; do
42 echo $in
43done
44echo finished=$in
45## STDOUT:
46a
47b
48c
49finished=c
50## END
51
52#### Tilde expansion within for loop
53HOME=/home/bob
54for name in ~/src ~/git; do
55 echo $name
56done
57## STDOUT:
58/home/bob/src
59/home/bob/git
60## END
61
62#### Brace Expansion within Array
63for i in -{a,b} {c,d}-; do
64 echo $i
65 done
66## STDOUT:
67-a
68-b
69c-
70d-
71## END
72## N-I dash STDOUT:
73-{a,b}
74{c,d}-
75## END
76
77#### using loop var outside loop
78fun() {
79 for i in a b c; do
80 echo $i
81 done
82 echo $i
83}
84fun
85## status: 0
86## STDOUT:
87a
88b
89c
90c
91## END
92
93#### continue
94for i in a b c; do
95 echo $i
96 if test $i = b; then
97 continue
98 fi
99 echo $i
100done
101## status: 0
102## STDOUT:
103a
104a
105b
106c
107c
108## END
109
110#### break
111for i in a b c; do
112 echo $i
113 if test $i = b; then
114 break
115 fi
116done
117## status: 0
118## STDOUT:
119a
120b
121## END
122
123#### while in while condition
124# This is a consequence of the grammar
125while while true; do echo cond; break; done
126do
127 echo body
128 break
129done
130## STDOUT:
131cond
132body
133## END
134
135#### while in pipe
136x=$(find spec/ | wc -l)
137y=$(find spec/ | while read path; do
138 echo $path
139done | wc -l
140)
141test $x -eq $y
142echo status=$?
143## stdout: status=0
144
145#### while in pipe with subshell
146i=0
147seq 3 | ( while read foo; do
148 i=$((i+1))
149 #echo $i
150done
151echo $i )
152## stdout: 3
153
154#### until loop
155# This is just the opposite of while? while ! cond?
156until false; do
157 echo hi
158 break
159done
160## stdout: hi
161
162#### continue at top level
163if true; then
164 echo one
165 continue
166 echo two
167fi
168## status: 0
169## STDOUT:
170one
171two
172## END
173# zsh behaves like strict_control_flow!
174## OK zsh status: 1
175## OK zsh STDOUT:
176one
177## END
178
179#### continue in subshell
180for i in $(seq 2); do
181 echo "> $i"
182 ( if true; then continue; fi; echo "Should not print" )
183 echo subshell status=$?
184 echo ". $i"
185done
186## STDOUT:
187# osh lets you fail
188> 1
189subshell status=1
190. 1
191> 2
192subshell status=1
193. 2
194## END
195## OK dash/zsh STDOUT:
196> 1
197subshell status=0
198. 1
199> 2
200subshell status=0
201. 2
202## END
203## BUG mksh/bash STDOUT:
204> 1
205Should not print
206subshell status=0
207. 1
208> 2
209Should not print
210subshell status=0
211. 2
212## END
213
214#### continue in subshell aborts with errexit
215# The other shells don't let you recover from this programming error!
216set -o errexit
217for i in $(seq 2); do
218 echo "> $i"
219 ( if true; then continue; fi; echo "Should not print" )
220 echo 'should fail after subshell'
221 echo ". $i"
222done
223
224## STDOUT:
225> 1
226## END
227## status: 1
228
229## BUG-2 dash/zsh STDOUT:
230> 1
231should fail after subshell
232. 1
233> 2
234should fail after subshell
235. 2
236## END
237## BUG-2 dash/zsh status: 0
238
239## BUG mksh/bash STDOUT:
240> 1
241Should not print
242should fail after subshell
243. 1
244> 2
245Should not print
246should fail after subshell
247. 2
248## END
249## BUG mksh/bash status: 0
250
251#### bad arg to break
252x=oops
253while true; do
254 echo hi
255 break $x
256 sleep 0.1
257done
258## stdout: hi
259## status: 1
260## OK dash status: 2
261## OK bash status: 128
262
263#### too many args to continue
264# OSH treats this as a parse error
265for x in a b c; do
266 echo $x
267 # bash breaks rather than continue or fatal error!!!
268 continue 1 2 3
269done
270echo --
271## stdout-json: ""
272## status: 2
273## BUG bash STDOUT:
274a
275--
276## END
277## BUG bash status: 0
278## BUG-2 dash/mksh/zsh STDOUT:
279a
280b
281c
282--
283## END
284## BUG-2 dash/mksh/zsh status: 0
285
286#### break in condition of loop
287while break; do
288 echo x
289done
290echo done
291## STDOUT:
292done
293## END
294
295
296#### break in condition of nested loop
297for i in 1 2 3; do
298 echo i=$i
299 while break; do
300 echo x
301 done
302done
303echo done
304## STDOUT:
305i=1
306i=2
307i=3
308done
309## END
310
311#### return within eval
312f() {
313 echo one
314 eval 'return'
315 echo two
316}
317f
318## STDOUT:
319one
320## END
321
322#### break/continue within eval
323# NOTE: This changes things
324# set -e
325f() {
326 for i in $(seq 5); do
327 if test $i = 2; then
328 eval continue
329 fi
330 if test $i = 4; then
331 eval break
332 fi
333 echo $i
334 done
335
336 eval 'return'
337 echo 'done'
338}
339f
340## STDOUT:
3411
3423
343## END
344## BUG mksh STDOUT:
3451
3462
3473
3484
3495
350## END
351
352#### break/continue within source
353# NOTE: This changes things
354# set -e
355
356cd $REPO_ROOT
357f() {
358 for i in $(seq 5); do
359 if test $i = 2; then
360 . spec/testdata/continue.sh
361 fi
362 if test $i = 4; then
363 . spec/testdata/break.sh
364 fi
365 echo $i
366 done
367
368 # Return is different!
369 . spec/testdata/return.sh
370 echo done
371}
372f
373## STDOUT:
3741
3753
376done
377## END
378## BUG zsh/mksh STDOUT:
3791
3802
3813
3824
3835
384done
385## END
386
387#### top-level break/continue/return (without strict_control_flow)
388$SH -c 'break; echo break=$?'
389$SH -c 'continue; echo continue=$?'
390$SH -c 'return; echo return=$?'
391## STDOUT:
392break=0
393continue=0
394## END
395## BUG-2 zsh STDOUT:
396## END
397## BUG bash STDOUT:
398break=0
399continue=0
400return=2
401## END
402
403
404#### multi-level break with argument
405
406# reported in issue #1459
407
408counterA=100
409counterB=100
410
411while test "$counterA" -gt 0
412do
413 counterA=$((counterA - 1))
414 while test "$counterB" -gt 0
415 do
416 counterB=$((counterB - 1))
417 if test "$counterB" = 50
418 then
419 break 2
420 fi
421 done
422done
423
424echo "$counterA"
425echo "$counterB"
426
427## STDOUT:
42899
42950
430## END
431
432
433#### multi-level continue
434
435for i in 1 2; do
436 for j in a b c; do
437 if test $j = b; then
438 continue
439 fi
440 echo $i $j
441 done
442done
443
444echo ---
445
446for i in 1 2; do
447 for j in a b c; do
448 if test $j = b; then
449 continue 2 # MULTI-LEVEL
450 fi
451 echo $i $j
452 done
453done
454
455## STDOUT:
4561 a
4571 c
4582 a
4592 c
460---
4611 a
4622 a
463## END
464
465#### $b break, $c continue, $r return, $e exit
466
467# hm would it be saner to make FATAL builtins called break/continue/etc.?
468# On the other hand, this spits out errors loudly.
469
470echo '- break'
471b=break
472for i in 1 2 3; do
473 echo $i
474 $b
475done
476
477echo '- continue'
478c='continue'
479for i in 1 2 3; do
480 if test $i = 2; then
481 $c
482 fi
483 echo $i
484done
485
486r='return'
487f() {
488 echo '- return'
489 for i in 1 2 3; do
490 echo $i
491 if test $i = 2; then
492 $r 99
493 fi
494 done
495}
496f
497echo status=$?
498
499echo '- exit'
500e='exit'
501$e 5
502echo 'not executed'
503
504## status: 5
505## STDOUT:
506- break
5071
508- continue
5091
5103
511- return
5121
5132
514status=99
515- exit
516## END
517
518#### \break \continue \return \exit
519
520echo '- break'
521for i in 1 2 3; do
522 echo $i
523 \break
524done
525
526echo '- continue'
527for i in 1 2 3; do
528 if test $i = 2; then
529 \continue
530 fi
531 echo $i
532done
533
534f() {
535 echo '- return'
536 for i in 1 2 3; do
537 echo $i
538 if test $i = 2; then
539 \return 99
540 fi
541 done
542}
543f
544echo status=$?
545
546echo '- exit'
547\exit 5
548echo 'not executed'
549
550## status: 5
551## STDOUT:
552- break
5531
554- continue
5551
5563
557- return
5581
5592
560status=99
561- exit
562## END
563
564#### builtin,command break,continue,return,exit
565case $SH in dash|zsh) exit ;; esac
566
567echo '- break'
568for i in 1 2 3; do
569 echo $i
570 builtin break
571done
572
573echo '- continue'
574for i in 1 2 3; do
575 if test $i = 2; then
576 command continue
577 fi
578 echo $i
579done
580
581f() {
582 echo '- return'
583 for i in 1 2 3; do
584 echo $i
585 if test $i = 2; then
586 builtin command return 99
587 fi
588 done
589}
590f
591echo status=$?
592
593echo '- exit'
594command builtin exit 5
595echo 'not executed'
596
597## status: 5
598## STDOUT:
599- break
6001
601- continue
6021
6033
604- return
6051
6062
607status=99
608- exit
609## END
610
611## N-I dash/zsh status: 0
612## N-I dash/zsh STDOUT:
613## END
614
615