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

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