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

702 lines, 394 significant
1## oils_failures_allowed: 3
2
3#### append onto BashArray a=(1 2)
4shopt -s parse_at
5a=(1 2)
6append '3 4' '5' (a)
7argv.py "${a[@]}"
8
9append -- 6 (a)
10argv.py "${a[@]}"
11
12## STDOUT:
13['1', '2', '3 4', '5']
14['1', '2', '3 4', '5', '6']
15## END
16
17#### append onto var a = :| 1 2 |
18shopt -s parse_at parse_proc
19var a = :| 1 2 |
20append '3 4' '5' (a)
21argv.py @a
22## STDOUT:
23['1', '2', '3 4', '5']
24## END
25
26#### append onto var a = ['1', '2']
27shopt -s parse_at parse_proc
28var a = ['1', '2']
29append '3 4' '5' (a)
30argv.py @a
31## STDOUT:
32['1', '2', '3 4', '5']
33## END
34
35#### append without typed arg
36append a b
37## status: 3
38
39#### append passed invalid type
40s=''
41append a b (s)
42echo status=$?
43## status: 3
44
45#### write --sep, --end, -n, varying flag syntax
46shopt -s ysh:all
47var a = %('a b' 'c d')
48write @a
49write .
50write -- @a
51write .
52
53write --sep '' --end '' @a; write
54write .
55
56write --sep '_' -- @a
57write --sep '_' --end b' END\n' -- @a
58
59write -n x
60write -n y
61write
62
63## STDOUT:
64a b
65c d
66.
67a b
68c d
69.
70a bc d
71.
72a b_c d
73a b_c d END
74xy
75## END
76
77#### write --json
78shopt --set ysh:upgrade
79
80write --json u'\u{3bc}' x
81write --json b'\yfe\yff' y
82
83## STDOUT:
84"μ"
85"x"
86"��"
87"y"
88## END
89
90#### write --j8
91shopt --set ysh:upgrade
92
93write --j8 u'\u{3bc}' x
94write --j8 b'\yfe\yff' y
95
96## STDOUT:
97"μ"
98"x"
99b'\yfe\yff'
100"y"
101## END
102
103#### write -e not supported
104shopt -s ysh:all
105write -e foo
106write status=$?
107## stdout-json: ""
108## status: 2
109
110#### write syntax error
111shopt -s ysh:all
112write ---end foo
113write status=$?
114## stdout-json: ""
115## status: 2
116
117#### write --
118shopt -s ysh:all
119write --
120# This is annoying
121write -- --
122write done
123
124# this is a syntax error! Doh.
125write ---
126## status: 2
127## STDOUT:
128
129--
130done
131## END
132
133#### read flag usage
134read --lin
135echo status=$?
136
137read --line :var extra
138echo status=$?
139## STDOUT:
140status=2
141status=2
142## END
143
144#### read (&x) is usage error
145
146var x = null # allow no initialization
147echo hello | read (&x)
148echo status=$?
149
150## STDOUT:
151status=2
152## END
153
154#### read --raw-line
155
156shopt --set parse_ysh_expr_sub
157
158echo hi | read --raw-line
159echo "reply=$_reply"
160echo len=$[len(_reply)]
161
162echo hi | read -r
163if test "$REPLY" = "$_reply"; then
164 echo pass
165fi
166
167## STDOUT:
168reply=hi
169len=2
170pass
171## END
172
173#### read --raw-line in a loop
174
175write --end '' $'\na\nb\n\n' | while read --raw-line; do
176 pp test_ (_reply)
177done
178
179echo
180
181write --end '' $'a\n\nb' | while read --raw-line; do
182 pp test_ (_reply)
183done
184
185
186## STDOUT:
187(Str) ""
188(Str) "a"
189(Str) "b"
190(Str) ""
191
192(Str) "a"
193(Str) ""
194(Str) "b"
195## END
196
197
198#### read --raw-line --with-eol in a loop
199
200write --end '' $'\na\nb\n\n' | while read --raw-line --with-eol; do
201 pp test_ (_reply)
202done
203
204echo
205
206write --end '' $'a\n\nb' | while read --raw-line --with-eol; do
207 pp test_ (_reply)
208done
209
210## STDOUT:
211(Str) "\n"
212(Str) "a\n"
213(Str) "b\n"
214(Str) "\n"
215
216(Str) "a\n"
217(Str) "\n"
218(Str) "b"
219## END
220
221#### Mixing read --raw-line with read -r
222
223$SH $REPO_ROOT/spec/testdata/ysh-read-0.sh
224
225## STDOUT:
226read -r
227REPLY=1
228REPLY=2
229
230read --raw-line
231_reply=1
232_reply=2
233
234Mixed
235REPLY=1
236REPLY=2
237_reply=3
238REPLY=4
239## END
240
241#### read --raw-line --with-eol
242
243$SH $REPO_ROOT/spec/testdata/ysh-read-1.sh
244
245## STDOUT:
246reply=1
247reply=2
248reply=3
249myline=a
250myline=b
251## END
252
253#### read --raw-line --j8
254
255# TODO: is this similar to @() ? It reads j8 lines?
256#
257# But using a function is better?
258#
259# var x = fromJ8Line(_reply)
260# var x = fromJson(_reply) # this is https://jsonlines.org
261
262echo $'u\'foo\'' | read --raw-line --j8
263write -- "$_reply"
264
265## STDOUT:
266foo
267## END
268
269#### echo builtin should disallow typed args - literal
270shopt -s ysh:all
271#shopt -p simple_echo
272
273echo (42)
274## status: 2
275## STDOUT:
276## END
277
278#### echo builtin should disallow typed args - variable
279shopt -s ysh:all
280#shopt -p simple_echo
281
282var x = 43
283echo (x)
284## status: 2
285## STDOUT:
286## END
287
288#### read --all-lines
289seq 3 | read --all-lines :nums
290write --sep ' ' -- @nums
291## STDOUT:
2921 2 3
293## END
294
295#### read --all-lines --with-eol
296seq 3 | read --all-lines --with-eol :nums
297write --sep '' -- @nums
298## STDOUT:
2991
3002
3013
302## END
303
304#### Can simulate read --all-lines with a proc and value.Place
305
306$SH $REPO_ROOT/spec/testdata/ysh-read-2.sh
307
308## STDOUT:
309[
310 "1",
311 "2",
312 "3"
313]
314## END
315
316#### read --all
317echo foo | read --all
318echo "[$_reply]"
319
320echo bad > tmp.txt
321read --all (&x) < tmp.txt
322echo "[$x]"
323
324## STDOUT:
325[foo
326]
327[bad
328]
329## END
330
331#### read --all from directory is an error (EISDIR)
332mkdir -p ./dir
333read --all < ./dir
334echo status=$?
335## STDOUT:
336status=1
337## END
338
339#### read --num-bytes
340
341echo ' a b ' | read --num-bytes 4; echo "reply=[$_reply]"
342echo ' a b ' | read --num-bytes 5; echo "reply=[$_reply]"
343
344echo ' a b ' | read --num-bytes 4 (&x); echo "x=[$x]"
345echo ' a b ' | read --num-bytes 5 (&x); echo "x=[$x]"
346
347## STDOUT:
348reply=[ a ]
349reply=[ a b]
350x=[ a ]
351x=[ a b]
352## END
353
354#### read -0 is like read -r -d ''
355set -o errexit
356
357mkdir -p read0
358cd read0
359touch a\\b\\c\\d
360
361find . -type f -a -print0 | read -r -d '' name
362echo "[$name]"
363
364find . -type f -a -print0 | read -0
365echo "[$REPLY]"
366
367## STDOUT:
368[./a\b\c\d]
369[./a\b\c\d]
370## END
371
372#### read -0 myvar doesn't do anything with IFS
373
374touch 'foo bar '
375find -type f -print0 | read -0
376echo "[$REPLY]"
377
378find -type f -print0 | read -0 myvar
379echo "[$myvar]"
380
381## STDOUT:
382[./foo bar ]
383[./foo bar ]
384## END
385
386#### simple_test_builtin
387
388test -n "foo"
389echo status=$?
390
391test -n "foo" -a -n "bar"
392echo status=$?
393
394[ -n foo ]
395echo status=$?
396
397echo ---
398
399shopt --set ysh:all
400shopt --unset errexit
401
402test -n "foo" -a -n "bar"
403echo status=$?
404
405[ -n foo ]
406echo status=$?
407
408test -z foo
409echo status=$?
410
411
412echo ---
413
414# The one arg form is disallowed because it's confusing that test -n test -n -n
415# are the same thing. In YSH, things that look like flags should be flags.
416test z
417echo status=$?
418
419test -z
420echo status=$?
421
422## STDOUT:
423status=0
424status=0
425status=0
426---
427status=2
428status=2
429status=1
430---
431status=2
432status=2
433## END
434
435#### long flags to test
436# no options necessary!
437
438test --dir /
439echo status=$?
440
441touch foo
442test --file foo
443echo status=$?
444
445test --exists /
446echo status=$?
447
448test --symlink foo
449echo status=$?
450
451test --typo foo
452echo status=$?
453
454## STDOUT:
455status=0
456status=0
457status=0
458status=1
459status=2
460## END
461
462#### test --true; test --false
463shopt --set ysh:upgrade
464
465for expr in (true, false, '', 'other') {
466 pp test_ (expr)
467
468 try {
469 test --true $[expr]
470 }
471 echo true=$[_error.code]
472
473 try {
474 test --false $[expr]
475 }
476 echo false=$[_error.code]
477 echo
478}
479
480## STDOUT:
481(Bool) true
482true=0
483false=1
484
485(Bool) false
486true=1
487false=0
488
489(Str) ""
490true=1
491false=1
492
493(Str) "other"
494true=1
495false=1
496
497## END
498
499#### More test --true --false
500shopt --set ysh:upgrade
501
502var d = {}
503
504try {
505 test --true $[bool(d)]
506}
507echo dict=$[_error.code]
508
509setvar d.key = 'val'
510
511try {
512 test --true $[bool(d)]
513}
514echo dict=$[_error.code]
515
516echo
517
518if test --true $[bool(d)] && ! test -f / {
519 echo AndOr
520}
521
522## STDOUT:
523dict=1
524dict=0
525
526AndOr
527## END
528
529
530#### Make sure [[ is not affected by --true --false
531
532set +o errexit
533
534$SH +o ysh:all -c '[[ --true ]]; echo dbracket=$?'
535$SH +o ysh:all -c '[[ --false ]]; echo dbracket=$?'
536
537$SH +o ysh:all -c '[[ --true true ]]; echo dbracket=$?'
538echo "parse error $?"
539$SH +o ysh:all -c '[[ --false false ]]; echo dbracket=$?'
540echo "parse error $?"
541
542## STDOUT:
543dbracket=0
544dbracket=0
545parse error 2
546parse error 2
547## END
548
549#### push-registers
550shopt --set ysh:upgrade
551shopt --unset errexit
552
553status_code() {
554 return $1
555}
556
557[[ foo =~ (.*) ]]
558
559status_code 42
560push-registers {
561 status_code 43
562 echo status=$?
563
564 [[ bar =~ (.*) ]]
565 echo ${BASH_REMATCH[@]}
566}
567# WEIRD SEMANTIC TO REVISIT: push-registers is "SILENT" as far as exit code
568# This is for the headless shell, but hasn't been tested.
569# Better method: maybe we should provide a way of SETTING $?
570
571echo status=$?
572
573echo ${BASH_REMATCH[@]}
574## STDOUT:
575status=43
576bar bar
577status=42
578foo foo
579## END
580
581#### push-registers usage
582shopt --set parse_brace
583
584push-registers
585echo status=$?
586
587push-registers a b
588echo status=$?
589
590push-registers a b { # hm extra args are ignored
591 echo hi
592}
593echo status=$?
594
595## STDOUT:
596status=2
597status=2
598hi
599status=0
600## END
601
602#### redir
603shopt --set parse_brace parse_proc
604
605proc p {
606 echo 'proc'
607}
608
609redir >out.txt {
610 p
611 echo 'builtin'
612}
613
614cat out.txt
615
616echo ---
617
618redir <out.txt {
619 tac
620}
621
622# Awkward bash syntax, but we'll live with it
623redir {left}>left.txt {right}>right.txt {
624 echo 1 >& $left
625 echo 1 >& $right
626
627 echo 2 >& $left
628 echo 2 >& $right
629
630 echo 3 >& $left
631}
632
633echo ---
634comm -23 left.txt right.txt
635
636## STDOUT:
637proc
638builtin
639---
640builtin
641proc
642---
6433
644## END
645
646#### type(x)
647shopt --set parse_ysh_expr_sub
648
649echo $[type(1234)]
650echo $[type('foo')]
651echo $[type(false)]
652echo $[type(1.234)]
653echo $[type([])]
654echo $[type({})]
655echo $[type(null)]
656
657shopt --set ysh:upgrade
658
659func f() {
660 return (42)
661}
662
663echo $[type(f)]
664echo $[type(len)]
665echo $[type('foo'=>startsWith)]
666echo $[type('foo'=>join)] # Type error happens later
667echo $[type(1..<3)]
668## STDOUT:
669Int
670Str
671Bool
672Float
673List
674Dict
675Null
676Func
677BuiltinFunc
678BoundFunc
679BoundFunc
680Range
681## END
682
683#### source ///osh/two.sh and $LIB_OSH
684
685source ///osh/two.sh
686echo status=$?
687
688source $LIB_OSH/two.sh
689echo status=$?
690
691# errors
692source ///
693echo status=$?
694source ///x
695echo status=$?
696
697## STDOUT:
698status=0
699status=0
700status=1
701status=1
702## END