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

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