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

411 lines, 229 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 '
240source --builtin ysh/shvar.ysh
241
242while true {
243 shvar FOO=foo {
244 echo shvar
245 continue
246 }
247}
248'
249echo shvar continue $?
250
251
252eval '
253while true {
254 try {
255 echo try
256 break
257 }
258}
259'
260echo try break $?
261
262## STDOUT:
263cd
264cd no loop 0
265cd
266cd loop 1
267shopt
268shopt continue 1
269shvar
270shvar continue 1
271try
272try break 1
273## END
274
275#### Consistency: Exit Status and Blocks
276shopt --set parse_brace
277
278source --builtin ysh/shvar.ysh
279
280cd / {
281 false
282}
283echo cd=$?
284
285shopt --unset errexit {
286 false
287}
288echo shopt=$?
289
290shvar FOO=foo {
291 echo " FOO=$FOO"
292 false
293}
294echo shvar=$?
295
296try {
297 false
298}
299echo try=$?
300
301## STDOUT:
302cd=0
303shopt=0
304 FOO=foo
305shvar=0
306try=0
307## END
308
309#### Consistency: Unwanted Blocks Are Errors
310shopt --set parse_brace
311
312true { echo BAD }
313echo true $?
314
315false ( 42, 43 )
316echo false $?
317
318echo { echo BAD }
319echo echo block $?
320
321echo ( 42, 43 )
322echo echo args $?
323
324command echo 'command block' { echo BAD }
325echo command echo $?
326
327builtin echo 'builtin block' { echo BAD }
328echo builtin echo $?
329
330pushd $TMP { echo BAD }
331echo pushd $?
332
333## STDOUT:
334true 2
335false 2
336echo block 2
337echo args 2
338command echo 2
339builtin echo 2
340pushd 2
341## END
342
343#### Block with Bare Assignments
344
345# oil:all has parse_equals
346# is there any way to turn on parse_equals only in config blocks?
347# but we don't know what's a block ahead of time
348# I think we would have to check at runtime. Look at VarChecker
349
350shopt --set oil:all
351
352proc Rule(s ; ; ; b) {
353 echo "rule $s"
354}
355
356proc myrules(name) {
357 Rule $name-python {
358 kind = 'python'
359 }
360
361 Rule $name-cc {
362 kind = 'cc' # should NOT conflict
363 }
364}
365
366myrules foo
367myrules bar
368
369## STDOUT:
370rule foo-python
371rule foo-cc
372rule bar-python
373rule bar-cc
374## END
375
376#### Proc that doesn't take a block
377shopt --set parse_brace parse_proc parse_paren
378
379proc task(name ; ; ; b = null) {
380 echo "task name=$name"
381 if (b) {
382 eval (b)
383 return 33
384 } else {
385 echo 'no block'
386 return 44
387 }
388}
389
390task spam
391echo status=$?
392
393echo
394
395task foo {
396 echo 'running'
397 echo 'block'
398}
399echo status=$?
400
401## STDOUT:
402task name=spam
403no block
404status=44
405
406task name=foo
407running
408block
409status=33
410## END
411