OILS / spec / loop.test.sh View on Github | oilshell.org

474 lines, 291 significant
1## compare_shells: dash bash-4.4 mksh zsh
2
3#### implicit for loop
4# This is like "for i in $@".
5fun() {
6 for i; do
7 echo $i
8 done
9}
10fun 1 2 3
11## STDOUT:
121
132
143
15## END
16
17#### empty for loop (has "in")
18set -- 1 2 3
19for i in ; do
20 echo $i
21done
22## stdout-json: ""
23
24#### for loop with invalid identifier
25# should be compile time error, but runtime error is OK too
26for - in a b c; do
27 echo hi
28done
29## stdout-json: ""
30## status: 2
31## OK bash/mksh status: 1
32## BUG zsh stdout: hi
33## BUG zsh status: 1
34
35#### the word 'in' can be the loop variable
36
37for in in a b c; do
38 echo $in
39done
40## STDOUT:
41a
42b
43c
44## END
45
46#### Tilde expansion within for loop
47HOME=/home/bob
48for name in ~/src ~/git; do
49 echo $name
50done
51## STDOUT:
52/home/bob/src
53/home/bob/git
54## END
55
56#### Brace Expansion within Array
57for i in -{a,b} {c,d}-; do
58 echo $i
59 done
60## STDOUT:
61-a
62-b
63c-
64d-
65## END
66## N-I dash STDOUT:
67-{a,b}
68{c,d}-
69## END
70
71#### using loop var outside loop
72fun() {
73 for i in a b c; do
74 echo $i
75 done
76 echo $i
77}
78fun
79## status: 0
80## STDOUT:
81a
82b
83c
84c
85## END
86
87#### continue
88for i in a b c; do
89 echo $i
90 if test $i = b; then
91 continue
92 fi
93 echo $i
94done
95## status: 0
96## STDOUT:
97a
98a
99b
100c
101c
102## END
103
104#### break
105for i in a b c; do
106 echo $i
107 if test $i = b; then
108 break
109 fi
110done
111## status: 0
112## STDOUT:
113a
114b
115## END
116
117#### dynamic control flow (KNOWN INCOMPATIBILITY)
118# hm would it be saner to make FATAL builtins called break/continue/etc.?
119# On the other hand, this spits out errors loudly.
120b=break
121for i in 1 2 3; do
122 echo $i
123 $b
124done
125## STDOUT:
1261
127## END
128## OK osh STDOUT:
1291
1302
1313
132## END
133## OK osh status: 127
134
135#### while in while condition
136# This is a consequence of the grammar
137while while true; do echo cond; break; done
138do
139 echo body
140 break
141done
142## STDOUT:
143cond
144body
145## END
146
147#### while in pipe
148x=$(find spec/ | wc -l)
149y=$(find spec/ | while read path; do
150 echo $path
151done | wc -l
152)
153test $x -eq $y
154echo status=$?
155## stdout: status=0
156
157#### while in pipe with subshell
158i=0
159seq 3 | ( while read foo; do
160 i=$((i+1))
161 #echo $i
162done
163echo $i )
164## stdout: 3
165
166#### until loop
167# This is just the opposite of while? while ! cond?
168until false; do
169 echo hi
170 break
171done
172## stdout: hi
173
174#### continue at top level
175if true; then
176 echo one
177 continue
178 echo two
179fi
180## status: 0
181## STDOUT:
182one
183two
184## END
185# zsh behaves like strict_control_flow!
186## OK zsh status: 1
187## OK zsh STDOUT:
188one
189## END
190
191#### continue in subshell
192for i in $(seq 2); do
193 echo "> $i"
194 ( if true; then continue; fi; echo "Should not print" )
195 echo subshell status=$?
196 echo ". $i"
197done
198## STDOUT:
199# osh lets you fail
200> 1
201subshell status=1
202. 1
203> 2
204subshell status=1
205. 2
206## END
207## OK dash/bash/zsh STDOUT:
208> 1
209subshell status=0
210. 1
211> 2
212subshell status=0
213. 2
214## END
215## BUG mksh STDOUT:
216> 1
217Should not print
218subshell status=0
219. 1
220> 2
221Should not print
222subshell status=0
223. 2
224## END
225
226#### continue in subshell aborts with errexit
227# The other shells don't let you recover from this programming error!
228set -o errexit
229for i in $(seq 2); do
230 echo "> $i"
231 ( if true; then continue; fi; echo "Should not print" )
232 echo 'should fail after subshell'
233 echo ". $i"
234done
235## STDOUT:
236> 1
237## END
238## status: 1
239## BUG dash/bash/zsh STDOUT:
240> 1
241should fail after subshell
242. 1
243> 2
244should fail after subshell
245. 2
246## END
247## BUG dash/bash/zsh status: 0
248## BUG mksh STDOUT:
249> 1
250Should not print
251should fail after subshell
252. 1
253> 2
254Should not print
255should fail after subshell
256. 2
257## END
258## BUG mksh status: 0
259
260#### bad arg to break
261x=oops
262while true; do
263 echo hi
264 break $x
265 sleep 0.1
266done
267## stdout: hi
268## status: 1
269## OK dash status: 2
270## OK bash status: 128
271
272#### too many args to continue
273# OSH treats this as a parse error
274for x in a b c; do
275 echo $x
276 # bash breaks rather than continue or fatal error!!!
277 continue 1 2 3
278done
279echo --
280## stdout-json: ""
281## status: 2
282## BUG bash STDOUT:
283a
284--
285## END
286## OK bash status: 0
287## BUG dash/mksh/zsh STDOUT:
288a
289b
290c
291--
292## END
293## BUG dash/mksh/zsh status: 0
294
295#### break in condition of loop
296while break; do
297 echo x
298done
299echo done
300## STDOUT:
301done
302## END
303
304
305#### break in condition of nested loop
306for i in 1 2 3; do
307 echo i=$i
308 while break; do
309 echo x
310 done
311done
312echo done
313## STDOUT:
314i=1
315i=2
316i=3
317done
318## END
319
320#### return within eval
321f() {
322 echo one
323 eval 'return'
324 echo two
325}
326f
327## STDOUT:
328one
329## END
330
331#### break/continue within eval
332# NOTE: This changes things
333# set -e
334f() {
335 for i in $(seq 5); do
336 if test $i = 2; then
337 eval continue
338 fi
339 if test $i = 4; then
340 eval break
341 fi
342 echo $i
343 done
344
345 eval 'return'
346 echo 'done'
347}
348f
349## STDOUT:
3501
3513
352## END
353## BUG mksh STDOUT:
3541
3552
3563
3574
3585
359## END
360
361#### break/continue within source
362# NOTE: This changes things
363# set -e
364
365cd $REPO_ROOT
366f() {
367 for i in $(seq 5); do
368 if test $i = 2; then
369 . spec/testdata/continue.sh
370 fi
371 if test $i = 4; then
372 . spec/testdata/break.sh
373 fi
374 echo $i
375 done
376
377 # Return is different!
378 . spec/testdata/return.sh
379 echo done
380}
381f
382## STDOUT:
3831
3843
385done
386## END
387## BUG zsh/mksh STDOUT:
3881
3892
3903
3914
3925
393done
394## END
395
396#### top-level break/continue/return (without strict_control_flow)
397$SH -c 'break; echo break=$?'
398$SH -c 'continue; echo continue=$?'
399$SH -c 'return; echo return=$?'
400## STDOUT:
401break=0
402continue=0
403## END
404## BUG zsh stdout-json: ""
405## BUG bash STDOUT:
406break=0
407continue=0
408return=1
409## END
410
411
412#### multi-level break with argument
413
414# reported in issue #1459
415
416counterA=100
417counterB=100
418
419while test "$counterA" -gt 0
420do
421 counterA=$((counterA - 1))
422 while test "$counterB" -gt 0
423 do
424 counterB=$((counterB - 1))
425 if test "$counterB" = 50
426 then
427 break 2
428 fi
429 done
430done
431
432echo "$counterA"
433echo "$counterB"
434
435## STDOUT:
43699
43750
438## END
439
440
441#### multi-level continue
442
443for i in 1 2; do
444 for j in a b c; do
445 if test $j = b; then
446 continue
447 fi
448 echo $i $j
449 done
450done
451
452echo ---
453
454for i in 1 2; do
455 for j in a b c; do
456 if test $j = b; then
457 continue 2 # MULTI-LEVEL
458 fi
459 echo $i $j
460 done
461done
462
463
464## STDOUT:
4651 a
4661 c
4672 a
4682 c
469---
4701 a
4712 a
472## END
473
474