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

698 lines, 392 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
156echo hi | read --raw-line
157echo "reply=$_reply"
158echo len=$[len(_reply)]
159
160echo hi | read -r
161if test "$REPLY" = "$_reply"; then
162 echo pass
163fi
164
165## STDOUT:
166reply=hi
167len=2
168pass
169## END
170
171#### read --raw-line in a loop
172
173write --end '' $'\na\nb\n\n' | while read --raw-line; do
174 pp test_ (_reply)
175done
176
177echo
178
179write --end '' $'a\n\nb' | while read --raw-line; do
180 pp test_ (_reply)
181done
182
183
184## STDOUT:
185(Str) ""
186(Str) "a"
187(Str) "b"
188(Str) ""
189
190(Str) "a"
191(Str) ""
192(Str) "b"
193## END
194
195
196#### read --raw-line --with-eol in a loop
197
198write --end '' $'\na\nb\n\n' | while read --raw-line --with-eol; do
199 pp test_ (_reply)
200done
201
202echo
203
204write --end '' $'a\n\nb' | while read --raw-line --with-eol; do
205 pp test_ (_reply)
206done
207
208## STDOUT:
209(Str) "\n"
210(Str) "a\n"
211(Str) "b\n"
212(Str) "\n"
213
214(Str) "a\n"
215(Str) "\n"
216(Str) "b"
217## END
218
219#### Mixing read --raw-line with read -r
220
221$SH $REPO_ROOT/spec/testdata/ysh-read-0.sh
222
223## STDOUT:
224read -r
225REPLY=1
226REPLY=2
227
228read --raw-line
229_reply=1
230_reply=2
231
232Mixed
233REPLY=1
234REPLY=2
235_reply=3
236REPLY=4
237## END
238
239#### read --raw-line --with-eol
240
241$SH $REPO_ROOT/spec/testdata/ysh-read-1.sh
242
243## STDOUT:
244reply=1
245reply=2
246reply=3
247myline=a
248myline=b
249## END
250
251#### read --raw-line --j8
252
253# TODO: is this similar to @() ? It reads j8 lines?
254#
255# But using a function is better?
256#
257# var x = fromJ8Line(_reply)
258# var x = fromJson(_reply) # this is https://jsonlines.org
259
260echo $'u\'foo\'' | read --raw-line --j8
261write -- "$_reply"
262
263## STDOUT:
264foo
265## END
266
267#### echo builtin should disallow typed args - literal
268shopt -s ysh:all
269#shopt -p simple_echo
270
271echo (42)
272## status: 2
273## STDOUT:
274## END
275
276#### echo builtin should disallow typed args - variable
277shopt -s ysh:all
278#shopt -p simple_echo
279
280var x = 43
281echo (x)
282## status: 2
283## STDOUT:
284## END
285
286#### read --all-lines
287seq 3 | read --all-lines :nums
288write --sep ' ' -- @nums
289## STDOUT:
2901 2 3
291## END
292
293#### read --all-lines --with-eol
294seq 3 | read --all-lines --with-eol :nums
295write --sep '' -- @nums
296## STDOUT:
2971
2982
2993
300## END
301
302#### Can simulate read --all-lines with a proc and value.Place
303
304$SH $REPO_ROOT/spec/testdata/ysh-read-2.sh
305
306## STDOUT:
307[
308 "1",
309 "2",
310 "3"
311]
312## END
313
314#### read --all
315echo foo | read --all
316echo "[$_reply]"
317
318echo bad > tmp.txt
319read --all (&x) < tmp.txt
320echo "[$x]"
321
322## STDOUT:
323[foo
324]
325[bad
326]
327## END
328
329#### read --all from directory is an error (EISDIR)
330mkdir -p ./dir
331read --all < ./dir
332echo status=$?
333## STDOUT:
334status=1
335## END
336
337#### read --num-bytes
338
339echo ' a b ' | read --num-bytes 4; echo "reply=[$_reply]"
340echo ' a b ' | read --num-bytes 5; echo "reply=[$_reply]"
341
342echo ' a b ' | read --num-bytes 4 (&x); echo "x=[$x]"
343echo ' a b ' | read --num-bytes 5 (&x); echo "x=[$x]"
344
345## STDOUT:
346reply=[ a ]
347reply=[ a b]
348x=[ a ]
349x=[ a b]
350## END
351
352#### read -0 is like read -r -d ''
353set -o errexit
354
355mkdir -p read0
356cd read0
357touch a\\b\\c\\d
358
359find . -type f -a -print0 | read -r -d '' name
360echo "[$name]"
361
362find . -type f -a -print0 | read -0
363echo "[$REPLY]"
364
365## STDOUT:
366[./a\b\c\d]
367[./a\b\c\d]
368## END
369
370#### read -0 myvar doesn't do anything with IFS
371
372touch 'foo bar '
373find -type f -print0 | read -0
374echo "[$REPLY]"
375
376find -type f -print0 | read -0 myvar
377echo "[$myvar]"
378
379## STDOUT:
380[./foo bar ]
381[./foo bar ]
382## END
383
384#### simple_test_builtin
385
386test -n "foo"
387echo status=$?
388
389test -n "foo" -a -n "bar"
390echo status=$?
391
392[ -n foo ]
393echo status=$?
394
395echo ---
396
397shopt --set ysh:all
398shopt --unset errexit
399
400test -n "foo" -a -n "bar"
401echo status=$?
402
403[ -n foo ]
404echo status=$?
405
406test -z foo
407echo status=$?
408
409
410echo ---
411
412# The one arg form is disallowed because it's confusing that test -n test -n -n
413# are the same thing. In YSH, things that look like flags should be flags.
414test z
415echo status=$?
416
417test -z
418echo status=$?
419
420## STDOUT:
421status=0
422status=0
423status=0
424---
425status=2
426status=2
427status=1
428---
429status=2
430status=2
431## END
432
433#### long flags to test
434# no options necessary!
435
436test --dir /
437echo status=$?
438
439touch foo
440test --file foo
441echo status=$?
442
443test --exists /
444echo status=$?
445
446test --symlink foo
447echo status=$?
448
449test --typo foo
450echo status=$?
451
452## STDOUT:
453status=0
454status=0
455status=0
456status=1
457status=2
458## END
459
460#### test --true; test --false
461shopt --set ysh:upgrade
462
463for expr in (true, false, '', 'other') {
464 pp test_ (expr)
465
466 try {
467 test --true $[expr]
468 }
469 echo true=$[_error.code]
470
471 try {
472 test --false $[expr]
473 }
474 echo false=$[_error.code]
475 echo
476}
477
478## STDOUT:
479(Bool) true
480true=0
481false=1
482
483(Bool) false
484true=1
485false=0
486
487(Str) ""
488true=1
489false=1
490
491(Str) "other"
492true=1
493false=1
494
495## END
496
497#### More test --true --false
498shopt --set ysh:upgrade
499
500var d = {}
501
502try {
503 test --true $[bool(d)]
504}
505echo dict=$[_error.code]
506
507setvar d.key = 'val'
508
509try {
510 test --true $[bool(d)]
511}
512echo dict=$[_error.code]
513
514echo
515
516if test --true $[bool(d)] && ! test -f / {
517 echo AndOr
518}
519
520## STDOUT:
521dict=1
522dict=0
523
524AndOr
525## END
526
527
528#### Make sure [[ is not affected by --true --false
529
530set +o errexit
531
532$SH +o ysh:all -c '[[ --true ]]; echo dbracket=$?'
533$SH +o ysh:all -c '[[ --false ]]; echo dbracket=$?'
534
535$SH +o ysh:all -c '[[ --true true ]]; echo dbracket=$?'
536echo "parse error $?"
537$SH +o ysh:all -c '[[ --false false ]]; echo dbracket=$?'
538echo "parse error $?"
539
540## STDOUT:
541dbracket=0
542dbracket=0
543parse error 2
544parse error 2
545## END
546
547#### push-registers
548shopt --set ysh:upgrade
549shopt --unset errexit
550
551status_code() {
552 return $1
553}
554
555[[ foo =~ (.*) ]]
556
557status_code 42
558push-registers {
559 status_code 43
560 echo status=$?
561
562 [[ bar =~ (.*) ]]
563 echo ${BASH_REMATCH[@]}
564}
565# WEIRD SEMANTIC TO REVISIT: push-registers is "SILENT" as far as exit code
566# This is for the headless shell, but hasn't been tested.
567# Better method: maybe we should provide a way of SETTING $?
568
569echo status=$?
570
571echo ${BASH_REMATCH[@]}
572## STDOUT:
573status=43
574bar bar
575status=42
576foo foo
577## END
578
579#### push-registers usage
580shopt --set parse_brace
581
582push-registers
583echo status=$?
584
585push-registers a b
586echo status=$?
587
588push-registers a b { # hm extra args are ignored
589 echo hi
590}
591echo status=$?
592
593## STDOUT:
594status=2
595status=2
596hi
597status=0
598## END
599
600#### redir
601shopt --set parse_brace parse_proc
602
603proc p {
604 echo 'proc'
605}
606
607redir >out.txt {
608 p
609 echo 'builtin'
610}
611
612cat out.txt
613
614echo ---
615
616redir <out.txt {
617 tac
618}
619
620# Awkward bash syntax, but we'll live with it
621redir {left}>left.txt {right}>right.txt {
622 echo 1 >& $left
623 echo 1 >& $right
624
625 echo 2 >& $left
626 echo 2 >& $right
627
628 echo 3 >& $left
629}
630
631echo ---
632comm -23 left.txt right.txt
633
634## STDOUT:
635proc
636builtin
637---
638builtin
639proc
640---
6413
642## END
643
644#### type(x)
645echo $[type(1234)]
646echo $[type('foo')]
647echo $[type(false)]
648echo $[type(1.234)]
649echo $[type([])]
650echo $[type({})]
651echo $[type(null)]
652
653shopt --set ysh:upgrade
654
655func f() {
656 return (42)
657}
658
659echo $[type(f)]
660echo $[type(len)]
661echo $[type('foo'=>startsWith)]
662echo $[type('foo'=>join)] # Type error happens later
663echo $[type(1..<3)]
664## STDOUT:
665Int
666Str
667Bool
668Float
669List
670Dict
671Null
672Func
673BuiltinFunc
674BoundFunc
675BoundFunc
676Range
677## END
678
679#### source ///osh/two.sh and $LIB_OSH
680
681source ///osh/two.sh
682echo status=$?
683
684source $LIB_OSH/two.sh
685echo status=$?
686
687# errors
688source ///
689echo status=$?
690source ///x
691echo status=$?
692
693## STDOUT:
694status=0
695status=0
696status=1
697status=1
698## END