1 ## our_shell: ysh
2 ## oils_failures_allowed: 6
3
4 #### fastlex: NUL byte inside shebang line
5
6 # Hm this test doesn't really tickle the bug
7
8 echo b'#! /usr/bin/env \y00 sh \necho hi' > tmp.ysh
9 env OILS_HIJACK_SHEBANG=1 $[ENV.SH] tmp.ysh
10
11 ## STDOUT:
12 hi
13 ## END
14
15 #### Tea keywords don't interfere with YSH expressions
16
17 var d = {data: 'foo'}
18
19 echo $[d.data]
20
21 var e = {enum: 1, class: 2, import: 3, const: 4, var: 5, set: 6}
22 echo $[len(e)]
23
24 ## STDOUT:
25 foo
26 6
27 ## END
28
29 #### Catch AttributeError
30
31 var s = 'foo'
32 echo s=$s
33 var t = s.bad()
34 echo 'should not get here'
35
36 ## status: 3
37 ## STDOUT:
38 s=foo
39 ## END
40
41
42 #### Command sub paren parsing bug (#1387)
43
44 write $(if (true) { write true })
45
46 const a = $(write $[len('foo')])
47 echo $a
48
49 const b = $(write $[5 ** 3])
50 echo $b
51
52 const c = $(
53 write $[6 + 7]
54 )
55 echo $c
56
57 ## STDOUT:
58 true
59 3
60 125
61 13
62 ## END
63
64
65 #### More Command sub paren parsing
66
67 write $( var mylist = ['for']; for x in (mylist) { echo $x } )
68
69 write $( echo while; while (false) { write hi } )
70
71 write $( if (true) { write 'if' } )
72
73 write $( if (false) { write 'if' } elif (true) { write 'elif' } )
74
75 ## STDOUT:
76 for
77 while
78 if
79 elif
80 ## END
81
82 #### don't execute empty command
83
84 shopt --set ysh:all
85
86 set -x
87
88 try {
89 type -a ''
90 }
91 echo "type -a returned $_status"
92
93 $(true)
94 echo nope
95
96 ## status: 127
97 ## STDOUT:
98 type -a returned 1
99 ## END
100
101
102 #### Do && || with YSH constructs make sense/
103
104 # I guess there's nothing wrong with this?
105 #
106 # But I generally feel && || are only for
107 #
108 # test --file x && test --file y
109
110 var x = []
111 true && call x->append(42)
112 false && call x->append(43)
113 pp test_ (x)
114
115 func amp() {
116 true && return (42)
117 }
118
119 func pipe() {
120 false || return (42)
121 }
122
123 pp test_ (amp())
124 pp test_ (pipe())
125
126 ## STDOUT:
127 ## END
128
129
130 #### shvar then replace - bug #1986 context manager crash
131
132 shvar FOO=bar {
133 for x in (1 ..< 500) {
134 var Q = "hello"
135 setvar Q = Q=>replace("hello","world")
136 }
137 }
138 #echo $Q
139 echo hi
140
141 ## STDOUT:
142 hi
143 ## END
144
145
146 #### Parsing crash - bug #2003
147
148 set +o errexit
149
150 $[ENV.SH] -c 'proc y (;x) { return = x }'
151 echo status=$?
152
153 $[ENV.SH] -c 'func y (;x) { return = x }'
154 echo status=$?
155
156 ## STDOUT:
157 status=2
158 status=2
159 ## END
160
161
162 #### proc with IFS= read -r line - dynamic scope - issue #2012
163
164 # 2024-10 - FIXED by the new Env Obj! Because in YSH, 'line' is NOT created in
165 # TEMP stack frame - we use the ENCLOSED frame, and it fixes it.
166
167 proc p {
168 read -r line
169 write $line
170 }
171
172 proc p-ifs {
173 IFS= read -r line
174 write $line
175 }
176
177 #set -x
178
179 echo zz | p
180
181 echo yy | p-ifs
182
183 ## STDOUT:
184 zz
185 yy
186 ## END
187
188 #### func call inside proc call - error message attribution
189
190 try 2> foo {
191 $[ENV.SH] -c '
192 func ident(x) {
193 return (x)
194 }
195
196 proc p (; x) {
197 echo $x
198 }
199
200 # BUG: it points to ( in ident(
201 # should point to ( in eval (
202
203 eval (ident([1,2,3]))
204 '
205 }
206
207 cat foo
208
209 ## STDOUT:
210 ## END
211
212
213 #### Crash in parsing case on EOF condition - issue #2037
214
215 var WEIGHT = ${1:-}
216 case (WEIGHT) {
217 "-" { echo "got nothing" }
218 (else) { echo $WEIGHT
219 }
220
221 ## status: 2
222 ## STDOUT:
223 ## END
224
225 #### Crash due to incorrect of context manager rooting - issue #1986
226
227 proc p {
228 var s = "hi"
229 for q in (1..<50) {
230 shvar Q="whatever" {
231 setvar s = "." ++ s
232 }
233 }
234 }
235
236 for i in (1..<10) {
237 p
238 }
239
240 if false {
241 echo 'testing for longer'
242 for i in (1 ..< 1000) {
243 p
244 }
245 }
246
247 ## STDOUT:
248 ## END
249
250
251 #### crash due to arbitrary PNode limit - issue #2078
252
253 #!/usr/bin/env ysh
254 var DelegatedCompName = {
255 "llvm" : "x_project",
256 "rocprofiler_register" : "x_rocprofiler_register",
257 "roct_thunk_interface" : "x_roct",
258 "rocr_runtime" : "x_rocr",
259 "openmp" : "x_openmp",
260 "offload" : "x_offload",
261 "aomp_extras" : "x_extras",
262 "comgr" : "x_comgr",
263 "rocminfo" : "x_rocminfo",
264 "rocsmilib" : "x_rocm_smi_lib",
265 "amdsmi" : "x_amdsmi",
266 "flang_legacy" : "x_flang_legacy",
267 "pgmath" : "x_pgmath",
268 "flang" : "x_flang",
269 "flang_runtime" : "x_flang_runtime",
270 "hipcc" : "x_hipcc",
271 "hipamd" : "x_hipamd",
272 "rocm_dbgapi" : "x_rocdbgapi",
273 "rocgdb" : "x_rocgdb",
274 "roctracer" : "x_roctracer",
275 "rocprofiler" : "x_rocprofiler"
276 }
277
278 echo $[len(DelegatedCompName)]
279
280 ## STDOUT:
281 21
282 ## END
283
284 #### bad assertion when pretty printing
285
286 pp value (__builtins__) > /dev/null
287 echo status=$?
288
289 ## STDOUT:
290 status=0
291 ## END
292
293 #### Another "stealing stdin" issue with spec tests
294
295 proc where2(; pred) {
296 for line in (io.stdin) {
297 pp test_ (line)
298 }
299 }
300
301 seq 5 | where2 [_line ~== 2 or _line ~== 4]
302
303 #{ echo 1; echo 2; } | where2 [_line ~== 2 or _line ~== 4]
304
305 # empty lines here get put on stdin
306
307 ## STDOUT:
308 (Str) "1"
309 (Str) "2"
310 (Str) "3"
311 (Str) "4"
312 (Str) "5"
313 ## END
314
315 #### Nested io.stdin
316
317 proc bug {
318 echo '''
319 proc inner {
320 printf 'a\nb\n' | for x in (io.stdin) {
321 echo x=$x
322 }
323 }
324
325 printf 'x\ny\n' | for _ in (io.stdin) {
326 inner
327 }
328 '''
329 }
330
331 # Changes with invocation style
332
333 $[ENV.SH] <(bug)
334 echo ---
335 $[ENV.SH] -c $(bug)
336 echo ---
337 bug | $[ENV.SH]
338
339 ## STDOUT:
340 x=a
341 x=b
342 x=a
343 x=b
344 ---
345 x=a
346 x=b
347 x=a
348 x=b
349 ---
350 x=a
351 x=b
352 x=a
353 x=b
354 ## END
355
356 #### Iterating over io.stdin multiple times (#2356)
357
358 echo u'a\nb' | for i, line in (io.stdin) { echo $i: $line; break }
359 echo u'c\nd' | for i, line in (io.stdin) { echo $i: $line }
360
361 ## STDOUT:
362 0: a
363 0: c
364 1: d
365 ## END
366
367 #### Long boolean flags can't have attached values
368
369 # This currently works, but I think --json and --j8 are enough?
370
371 write --json=0 hi
372 write --json=F hi
373 write --json=False hi
374 write --json=false hi
375 echo
376
377 write --json=1 hi
378 write --json=T hi
379 write --json=True hi
380 write --json=true hi
381
382 # typo bug
383 write --json=Talse hi
384
385 ## status: 1
386 ## STDOUT:
387 ## END
388
389 #### Bug: rooting of pgen2::PNode
390
391 # manifests with _bin/cxx-asan+gcalways/ysh, after turning on VALIDATE_ROOTS
392
393 var x = 42
394 echo $x
395
396 #var y = 'foo-' ++ $(var y = 42; echo $y)
397
398 ## STDOUT:
399 42
400 ## END