OILS / spec / ysh-blocks.test.sh View on Github | oils.pub

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