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