OILS / spec / ysh-blocks.test.sh View on Github | oilshell.org

407 lines, 228 significant
1#### cd accepts a block, runs it in different dir
2shopt -s ysh:all
3
4const saved = "$PWD"
5
6# OLDPWD is NOT defined
7cd / { echo $PWD; echo OLDPWD=${OLDPWD:-} }; echo done
8
9if ! test "$saved" = $PWD; then
10 echo FAIL
11fi
12
13cd /tmp {
14 write PWD=$PWD
15 write --sep ' ' pwd builtin: $(pwd)
16}
17
18if ! test "$saved" = $PWD; then
19 echo FAIL
20fi
21
22## STDOUT:
23/
24OLDPWD=
25done
26PWD=/tmp
27pwd builtin: /tmp
28## END
29
30#### cd with block: requires explicit command
31shopt --set ysh:upgrade
32
33cd /tmp { echo $PWD }
34
35HOME=~
36cd { echo $PWD }
37
38## status: 2
39## STDOUT:
40/tmp
41## END
42
43#### cd with block: fatal error in block
44shopt -s ysh:all
45cd / {
46 echo one
47 false
48 echo two
49}
50## status: 1
51## STDOUT:
52one
53## END
54
55
56#### cd with block: return in block
57shopt -s oil:all
58f() {
59 cd / {
60 echo one
61 return
62 echo two
63 }
64 echo 'end func'
65}
66f
67## STDOUT:
68one
69end func
70## END
71
72#### cd with block: break in block
73shopt -s oil:all
74f() {
75 cd / {
76 echo one
77 for i in 1 2; do
78 echo $i
79 break # break out of loop
80 done
81
82 break # break out of block isn't valid
83 echo two
84 }
85 echo end func
86}
87f
88## status: 1
89## STDOUT:
90one
911
92## END
93
94#### cd with block exits with status 0
95shopt -s ysh:all
96cd / {
97 echo block
98
99 # This return value is ignored.
100 # Or maybe this should be a runtime error?
101 return 1
102}
103echo status=$?
104## STDOUT:
105block
106status=0
107## END
108
109#### block doesn't have its own scope
110shopt -s ysh:all
111var x = 1
112echo "x=$x"
113cd / {
114 #set y = 5 # This would be an error because set doesn't do dynamic lookup
115 var x = 42
116 echo "x=$x"
117}
118echo "x=$x"
119## STDOUT:
120x=1
121x=42
122x=42
123## END
124
125#### redirects allowed in words, typed args, and after block
126shopt -s ysh:upgrade
127
128rm -f out
129touch out
130
131cd /tmp >>out {
132 echo 1 $PWD
133}
134
135cd /tmp >>out (; ; ^(echo 2 $PWD))
136
137cd /tmp (; ; ^(echo 3 $PWD)) >>out
138
139cd /tmp {
140 echo 4 $PWD
141} >> out
142
143cat out
144
145## STDOUT:
1461 /tmp
1472 /tmp
1483 /tmp
1494 /tmp
150## END
151
152#### block literal in expression mode: ^(echo $PWD)
153shopt -s oil:all
154
155const myblock = ^(echo $PWD | wc -l)
156eval (myblock)
157
158const b2 = ^(echo one; echo two)
159eval (b2)
160
161## STDOUT:
1621
163one
164two
165## END
166
167#### block arg as typed expression
168
169shopt -s oil:all
170
171# literal
172cd /tmp (; ; ^(echo $PWD))
173
174const myblock = ^(echo $PWD)
175cd /tmp (; ; myblock)
176
177## STDOUT:
178/tmp
179/tmp
180## END
181
182#### Pass invalid typed args
183
184cd /tmp (42) # should be a block
185## status: 3
186
187#### Pass too many typed args
188
189cd /tmp (1, 2)
190## status: 3
191
192#### 'builtin' and 'command' with block
193shopt --set oil:upgrade
194builtin cd / {
195 echo "builtin $PWD"
196}
197command cd / {
198 echo "command $PWD"
199}
200## STDOUT:
201builtin /
202command /
203## END
204
205
206#### Consistency: Control Flow and Blocks
207shopt --set parse_brace
208
209# "Invalid control flow at top level"
210eval '
211 cd / {
212 echo cd
213 break
214 }
215'
216echo cd no loop $?
217
218# warning: "Unexpected control flow in block" (strict_control_flow)
219eval '
220while true {
221 cd / {
222 echo cd
223 break
224 }
225}
226'
227echo cd loop $?
228
229eval '
230while true {
231 shopt --unset errexit {
232 echo shopt
233 continue
234 }
235}
236'
237echo shopt continue $?
238
239eval '
240while true {
241 shvar FOO=foo {
242 echo shvar
243 continue
244 }
245}
246'
247echo shvar continue $?
248
249
250eval '
251while true {
252 try {
253 echo try
254 break
255 }
256}
257'
258echo try break $?
259
260## STDOUT:
261cd
262cd no loop 0
263cd
264cd loop 1
265shopt
266shopt continue 1
267shvar
268shvar continue 1
269try
270try break 1
271## END
272
273#### Consistency: Exit Status and Blocks
274shopt --set parse_brace
275
276cd / {
277 false
278}
279echo cd=$?
280
281shopt --unset errexit {
282 false
283}
284echo shopt=$?
285
286shvar FOO=foo {
287 echo " FOO=$FOO"
288 false
289}
290echo shvar=$?
291
292try {
293 false
294}
295echo try=$?
296
297## STDOUT:
298cd=0
299shopt=0
300 FOO=foo
301shvar=0
302try=0
303## END
304
305#### Consistency: Unwanted Blocks Are Errors
306shopt --set parse_brace
307
308true { echo BAD }
309echo true $?
310
311false ( 42, 43 )
312echo false $?
313
314echo { echo BAD }
315echo echo block $?
316
317echo ( 42, 43 )
318echo echo args $?
319
320command echo 'command block' { echo BAD }
321echo command echo $?
322
323builtin echo 'builtin block' { echo BAD }
324echo builtin echo $?
325
326pushd $TMP { echo BAD }
327echo pushd $?
328
329## STDOUT:
330true 2
331false 2
332echo block 2
333echo args 2
334command echo 2
335builtin echo 2
336pushd 2
337## END
338
339#### Block with Bare Assignments
340
341# oil:all has parse_equals
342# is there any way to turn on parse_equals only in config blocks?
343# but we don't know what's a block ahead of time
344# I think we would have to check at runtime. Look at VarChecker
345
346shopt --set oil:all
347
348proc Rule(s ; ; ; b) {
349 echo "rule $s"
350}
351
352proc myrules(name) {
353 Rule $name-python {
354 kind = 'python'
355 }
356
357 Rule $name-cc {
358 kind = 'cc' # should NOT conflict
359 }
360}
361
362myrules foo
363myrules bar
364
365## STDOUT:
366rule foo-python
367rule foo-cc
368rule bar-python
369rule bar-cc
370## END
371
372#### Proc that doesn't take a block
373shopt --set parse_brace parse_proc parse_paren
374
375proc task(name ; ; ; b = null) {
376 echo "task name=$name"
377 if (b) {
378 eval (b)
379 return 33
380 } else {
381 echo 'no block'
382 return 44
383 }
384}
385
386task spam
387echo status=$?
388
389echo
390
391task foo {
392 echo 'running'
393 echo 'block'
394}
395echo status=$?
396
397## STDOUT:
398task name=spam
399no block
400status=44
401
402task name=foo
403running
404block
405status=33
406## END
407