1 #### benchmark.fact5.test
2 fact() {
3 n=$1
4 if [ "$n" -le 0 ]
5 then echo 1
6 else echo $((n * $(fact $(($n-1)) ) ))
7 fi
8 }
9
10 fact 5
11
12 timing=$(times | head -n 1)
13 minutes=$(echo $timing | sed 's/\([0-9]*\)m\([0-9]*\).\([0-9]*\)s.*/\1/')
14 seconds=$(echo $timing | sed 's/\([0-9]*\)m\([0-9]*\).\([0-9]*\)s.*/\2/')
15 fractional=$(echo $timing | sed 's/\([0-9]*\)m\([0-9]*\).\([0-9]*\)s.*/\3/')
16
17 [ "$minutes" -eq 0 ] && [ "$seconds" -eq 0 ] && [ 1"$fractional" -lt 1001000 ]
18
19 ## STDOUT:
20 120
21 ## END
22
23 #### benchmark.while.test
24 x=0
25 while [ $x -lt 500 ]
26 do
27 : $((x+=1))
28 done
29 echo $x
30
31 timing=$(times | head -n 1)
32 minutes=$(echo $timing | sed 's/\([0-9]*\)m\([0-9]*\).\([0-9]*\)s.*/\1/')
33 seconds=$(echo $timing | sed 's/\([0-9]*\)m\([0-9]*\).\([0-9]*\)s.*/\2/')
34 fractional=$(echo $timing | sed 's/\([0-9]*\)m\([0-9]*\).\([0-9]*\)s.*/\3/')
35
36 if [ "$CI" ] # lolsob
37 then
38 target=002000
39 else
40 target=001000
41 fi
42
43 [ "$minutes" -eq 0 ] && [ "$seconds" -eq 0 ] && [ 1"$fractional" -lt 1"$target" ]
44
45
46 ## STDOUT:
47 500
48 ## END
49
50 #### builtin.alias.empty.test
51 set -e
52
53 alias empty=''
54 empty
55
56 ## stdout-json: ""
57
58 #### builtin.break.lexical.test
59 brk() { break 5 2>/dev/null; echo post; }
60 i=0; while [ $i -lt 5 ]; do echo $i; brk; : $((i+=1)); done
61 ## STDOUT:
62 0
63 post
64 1
65 post
66 2
67 post
68 3
69 post
70 4
71 post
72 ## END
73
74 #### builtin.break.nonlexical.test
75 set -o nonlexicalctrl 2>/dev/null
76 brk() { break 5 2>/dev/null; echo post; }
77 i=0; while [ $i -lt 5 ]; do echo $i; brk; : $((i+=1)); done
78 ## STDOUT:
79 0
80 ## END
81
82 #### builtin.cd.pwd.test
83 pwd -P # resolve physical PWD
84 orig=$(pwd)
85 echo $orig $PWD
86 [ "$orig" = "$PWD" ] || exit 1
87 mkdir inner
88 cd inner
89 [ "$orig"/inner = "$PWD" ] || exit 2
90 [ $(pwd) = "$PWD" ] || exit 3
91 cd ..
92 [ "$orig" = "$PWD" ] || exit 4
93 [ $(pwd) = "$PWD" ] || exit 5
94
95
96 #### builtin.command.ec.test
97 false
98 command -V alias >/dev/null
99 ec=$?
100 echo $ec
101 [ $ec -eq 0 ] || exit 1
102 false
103 x=$(command -V alias)
104 ec=$?
105 echo $ec
106 [ $ec -eq 0 ] || exit 2
107 command -V nonesuch >/dev/null && exit 3
108 exit 0
109 ## STDOUT:
110 0
111 0
112 ## END
113
114 #### builtin.command.exec.test
115 echo hi >file
116 command exec 8<file
117 read msg <&8
118 echo $msg
119 ## STDOUT:
120 hi
121 ## END
122
123 #### builtin.command.keyword.test
124 # ADDTOPOSIX
125 set -e
126 command -v !
127 command -v while
128 command -V while >/dev/null 2>&1
129 type do >/dev/null 2>&1
130 ## STDOUT:
131 !
132 while
133 ## END
134
135 #### builtin.command.nospecial.test
136 command readonly x=foo
137 command readonly x=bar
138 echo ?=$?
139
140 ## STDOUT:
141 ?=1
142 ## END
143
144 #### builtin.command.special.assign.test
145 unset x
146 x=whoops command :
147 echo ${x-unset}
148 ## STDOUT:
149 unset
150 ## END
151
152 #### builtin.continue.lexical.test
153 cnt() { continue 5 2>/dev/null; echo post; }
154 i=0; while [ $i -lt 5 ]; do echo $i; : $((i+=1)); cnt; echo after; done
155 ## STDOUT:
156 0
157 post
158 after
159 1
160 post
161 after
162 2
163 post
164 after
165 3
166 post
167 after
168 4
169 post
170 after
171 ## END
172
173 #### builtin.continue.nonlexical.test
174 set -o nonlexicalctrl 2>/dev/null
175 cnt() { continue 2>/dev/null; echo post; }
176 i=0; while [ $i -lt 5 ]; do echo $i; : $((i+=1)); cnt; echo after; done
177 ## STDOUT:
178 0
179 1
180 2
181 3
182 4
183 ## END
184
185 #### builtin.dot.break.test
186 echo break >scr
187 for x in a b c
188 do
189 echo $x
190 . ./scr
191 done
192 ## STDOUT:
193 a
194 b
195 c
196 ## END
197
198 #### builtin.dot.nonexistent.test
199 . ./nonesuch
200
201 ## status: 1
202 ## stdout-json: ""
203
204 #### builtin.dot.path.test
205 set -e
206
207 # manual cleanup to avoid prompt
208 mkdir p1 p2
209 trap 'rm -rf p1 p2' EXIT
210
211 cat >scr1 <<EOF
212 PATH="$(pwd)/p1:$(pwd)/p2:$PATH"
213 . scr2
214 EOF
215
216 echo 'echo nope' >p1/scr2
217 echo 'echo yep' >p2/scr2
218
219 chmod -f 333 p1/scr2
220 chmod -f 444 p2/scr2
221
222 $TEST_SHELL scr1
223
224
225 ## STDOUT:
226 yep
227 ## END
228
229 #### builtin.dot.return.test
230 cat >scr <<EOF
231 echo always
232 (exit 47)
233 return
234 echo never
235 EOF
236 . ./scr
237 [ $? -eq 47 ] || exit 1
238 echo done
239 ## STDOUT:
240 always
241 done
242 ## END
243
244 #### builtin.dot.unreadable.test
245 set -e
246
247 echo echo yes >weird
248 . ./weird
249
250 echo echo no >weird
251 chmod a-r weird
252 ! $TEST_SHELL -c '. ./weird'
253 rm -f weird
254 echo done
255 ## STDOUT:
256 yes
257 done
258 ## END
259
260 #### builtin.echo.exitcode.test
261 # Make sure that echo properly sets its exitcode.
262 echo >/dev/null && echo OK
263 echo >/dev/full || echo OK
264
265 ## STDOUT:
266 OK
267 OK
268 ## END
269
270 #### builtin.eval.break.test
271 for x in a b c; do echo $x; eval break; done
272
273 ## STDOUT:
274 a
275 ## END
276
277 #### builtin.eval.test
278 echo starting
279 eval echo hi
280 echo nice
281 eval "x=bye"
282 echo $x
283
284
285 ## STDOUT:
286 starting
287 hi
288 nice
289 bye
290 ## END
291
292 #### builtin.eval.trap.test
293 # Harald van Dijk <harald@gigawatt.nl> (2020-01-06) (inbox list)
294 # Subject: EXIT trap handling in subshells broken
295 # To: DASH shell mailing list <dash@vger.kernel.org>
296 # Date: Mon, 06 Jan 2020 21:57:20 +0000
297
298 eval '(trap "echo bug" EXIT)' >/dev/null
299 echo ok
300 ## STDOUT:
301 ok
302 ## END
303
304 #### builtin.exec.badredir.test
305 exec 9&<-
306
307 ## status: 1
308 ## stdout-json: ""
309
310 #### builtin.exec.modernish.mkfifo.loop.test
311 [ -e pipe ] && rm pipe
312 mkfifo pipe
313 ( echo hello >&8 ) 8>pipe &
314 command exec 8<pipe
315 read -r line <&8 ; echo $?
316 echo read [${line-UNSET}]
317 ## STDOUT:
318 0
319 read [hello]
320 ## END
321
322 #### builtin.exec.noargs.ec.test
323 false || command exec
324 echo ok
325
326 ## STDOUT:
327 ok
328 ## END
329
330 #### builtin.exec.true.test
331 exec true
332 false
333
334
335 #### builtin.exit0.test
336 exit 0
337
338
339 #### builtin.exitcode.test
340 # Check if builtin commands properly set their exit codes.
341
342 high_exit() {
343 return 42
344 }
345
346 # break, continue, exit, return and newgrp are not tested.
347 COMMANDS=": shift unset export readonly local times eval source exec
348 set trap true false pwd echo cd hash type command umask alias unalias
349 wait jobs read test [ printf kill getopts fg bg help history fc
350 ulimit"
351
352 # Check if every command sets the exit code for itself.
353 echo Leaking commands:
354 for command in $COMMANDS; do
355 high_exit
356 rc=$($command </dev/null >/dev/null 2>/dev/null; echo $?)
357 if [ -z $rc ]; then
358 # Skip if for some reason the subshell failed.
359 continue
360 elif [ $rc -eq 42 ]; then
361 echo $command
362 fi
363 done
364
365 # Check if any command lies about its failure.
366 echo Silently failing commands:
367 for command in $COMMANDS; do
368 has_output=$($command </dev/null 2>&1 | wc -c)
369 if [ $has_output -eq 0 ]; then
370 continue
371 fi
372 true
373 rc=$($command </dev/null >/dev/full 2>/dev/full; echo $?)
374 if [ -z $rc ]; then
375 continue
376 elif [ $rc -eq 0 ]; then
377 echo $command
378 fi
379 done
380
381 # More involved cases.
382 export FOO=1
383 readonly FOO
384 alias foo=bar
385 alias baz=qux
386 while read command; do
387 true
388 rc=$($command </dev/null >/dev/full 2>/dev/full; echo $?)
389 if [ -z $rc ]; then
390 continue
391 elif [ $rc -eq 0 ]; then
392 echo $command
393 fi
394 done <<EOF
395 export -p
396 readonly -p
397 type echo
398 command -p ''
399 command -v echo
400 command -V echo
401 alias
402 alias foo
403 alias foo baz
404 alias bar
405 printf "foo"
406 kill -l
407 kill -l 1
408 kill -l 2 3
409 help builtins
410 help version
411 help trace
412 help spec
413 EOF
414
415 ## STDOUT:
416 Leaking commands:
417 Silently failing commands:
418 ## END
419
420 #### builtin.export.override.test
421 unset x
422 $TEST_UTIL/getenv x
423 x=4
424 $TEST_UTIL/getenv x
425 export x=5
426 $TEST_UTIL/getenv x
427 x=6 $TEST_UTIL/getenv x
428 echo x is ${x-unset}
429
430 ## STDOUT:
431 x is unset
432 x is unset
433 x='5'
434 x='6'
435 x is 5
436 ## END
437
438 #### builtin.export.test
439 cat >scr <<'EOF'
440 echo ${var-unset}
441 EOF
442 $TEST_SHELL scr
443 var=hi
444 $TEST_SHELL scr
445 var=here $TEST_SHELL scr
446 export var=bye
447 $TEST_SHELL scr
448
449 ## STDOUT:
450 unset
451 unset
452 here
453 bye
454 ## END
455
456 #### builtin.export.unset.test
457 set -e
458 unset x
459 export x
460 export -p | grep 'export x'
461 echo ok
462 ## STDOUT:
463 export x
464 ok
465 ## END
466
467 #### builtin.falsetrue.test
468 false || true
469
470
471 #### builtin.hash.nonposix.test
472 ls >/dev/null
473 hash | grep ls >/dev/null || exit 1
474 touch hi
475 hash | grep ls >/dev/null || exit 2
476 hash | grep touch >/dev/null || exit 3
477 hash -r
478 hash | grep ls >/dev/null && exit 4
479 hash | grep touch >/dev/null && exit 5
480 echo ok
481 ## STDOUT:
482 ok
483 ## END
484
485 #### builtin.jobs.test
486 sleep 10 & pid=$!
487 sleep 1
488 jobs >job_info
489 grep "sleep 10" job_info >/dev/null || exit 1
490 grep "[1]" job_info >/dev/null || exit 2
491 kill $pid
492
493 rm job_info
494 unset j pid
495
496 sleep 10 & pid=$!
497 sleep 1
498 jobs -l >job_info
499 grep "sleep 10" job_info >/dev/null || exit 3
500 grep "[1]" job_info >/dev/null || exit 4
501 grep $pid job_info >/dev/null || exit 5
502 kill $pid
503
504 rm job_info
505 ## stdout-json: ""
506
507 #### builtin.kill0_+5.test
508 ! kill -s 0 $(($$+5))
509
510
511 #### builtin.kill0.test
512 kill -s 0 $$
513
514
515 #### builtin.kill.jobs.test
516 sleep 5 & pid1=$!
517 sleep 6 & pid2=$!
518 start=$(date "+%s")
519 sleep 1
520 kill %1 %2 && exit 3
521 kill $pid1 $pid2
522 wait
523 stop=$(date "+%s")
524 elapsed=$((stop - start))
525 echo $stop - $start = $elapsed
526 [ $((elapsed)) -lt 3 ] || exit 1
527
528 echo setting -m
529 set -m
530 echo sleeping
531 jobs -l
532 sleep 5 & pid1=$!
533 sleep 6 & pid2=$!
534 start=$(date "+%s")
535 sleep 1
536 jobs -l
537 kill %1 %2
538 wait
539 stop=$(date "+%s")
540 elapsed=$((stop - start))
541 echo $stop - $start = $elapsed
542 [ $((elapsed)) -lt 3 ] || exit 2
543
544
545 #### builtin.kill.signame.test
546 rm -f foo
547 set -e
548
549 trap 'touch foo' TERM
550
551 kill $$
552 [ -f foo ] && ! [ -s foo ]
553 rm foo
554 echo plain kill
555
556 kill -TERM $$
557 [ -f foo ] && ! [ -s foo ]
558 rm foo
559 echo named \(-TERM\)
560
561 kill -15 $$
562 [ -f foo ] && ! [ -s foo ]
563 rm foo
564 echo numbered \(-15\)
565
566 ## STDOUT:
567 plain kill
568 named (-TERM)
569 numbered (-15)
570 ## END
571
572 #### builtin.printf.repeat.test
573 printf '%d %d\n' 1 2 3 4 5 6 7 8 9
574 ## STDOUT:
575 1 2
576 3 4
577 5 6
578 7 8
579 9 0
580 ## END
581
582 #### builtin.pwd.exitcode.test
583 # Make sure that pwd sets its exitcode.
584 false
585 pwd >/dev/null 2>/dev/null && echo OK
586
587 ## STDOUT:
588 OK
589 ## END
590
591 #### builtin.readonly.assign.noninteractive.test
592 readonly a=b
593 export a=c
594 echo egad
595
596 ## status: 1
597 ## stdout-json: ""
598
599 #### builtin.set.-m.test
600 set -m
601 echo hi
602
603 ## STDOUT:
604 hi
605 ## END
606
607 #### builtin.set.quoted.test
608 myvar='a b c'
609 set | grep myvar >scr
610 . ./scr
611 printf '%s\n' $myvar
612
613 ## STDOUT:
614 a
615 b
616 c
617 ## END
618
619 #### builtin.source.nonexistent.earlyexit.test
620 source not_a_thing
621 echo hi
622 exit 0
623 ## status: 1
624 ## stdout-json: ""
625
626 #### builtin.source.nonexistent.test
627 source nonesuch
628 . nonesuch
629
630 ## status: 1
631 ## stdout-json: ""
632
633 #### builtin.source.setvar.test
634 set -e
635
636 echo 'x=5' >to_source
637 source ./to_source
638 echo ${x?:unset}
639 rm to_source
640 [ "$x" -eq 5 ]
641 ## STDOUT:
642 5
643 ## END
644
645 #### builtin.special.redir.error.test
646 : 2>&9
647 echo oh no
648
649 ## status: 1
650 ## stdout-json: ""
651
652 #### builtin.test.bigint.test
653 ! test -t 12323454234578326584376438
654 echo ok
655 ## STDOUT:
656 ok
657 ## END
658
659 #### builtin.test.nonposix.test
660 touch first
661 [ first -ef first ] || exit 3
662 sleep 1
663 touch second
664 [ second -nt first ] || exit 3
665 [ second -ot first ] && exit 4
666 [ first -ot second ] || exit 5
667 [ first -nt second ] && exit 6
668 mkdir up
669 [ first -ef up/../first ] || exit 7
670 [ first -ef up/../up/../second ] && exit 8
671 exit 0
672
673
674 #### builtin.test.-nt.-ot.absent.test
675 touch present
676 [ present -nt absent ] || exit 1
677 [ absent -ot present ] || exit 2
678
679
680 #### builtin.test.numeric.spaces.nonposix.test
681 test " 5" -eq " 5 "
682
683
684 #### builtin.test.symlink.test
685 echo hi >file
686 mkdir dir
687 ln -s file link_file
688 ln -s dir link_dir
689 [ -e file ] && [ -e link_file ] && \
690 [ -f file ] && [ -f link_file ] && \
691 [ -e dir ] && [ -e link_dir ] && \
692 [ -d dir ] && [ -d link_dir ] && \
693 [ -L link_file ] && [ -L link_dir ]
694
695 #### builtin.times.ioerror.test
696 exec 3>&1
697 (
698 trap "" PIPE
699 sleep 1
700 command times
701 echo ?=$? >&3
702 ) | true
703
704 ## STDOUT:
705 ?=2
706 ## END
707
708 #### builtin.trap.chained.test
709 # https://www.spinics.net/lists/dash/msg01771.html
710 trap exit INT
711 trap 'true; kill -s INT $$' EXIT
712 false
713
714
715 #### builtin.trap.exit3.test
716 # https://www.spinics.net/lists/dash/msg01750.html
717 trap '(exit 3) && echo BUG' INT
718 kill -s INT $$
719
720 ## stdout-json: ""
721
722 #### builtin.trap.exitcode.test
723 # https://www.spinics.net/lists/dash/msg01770.html
724
725 trap 'set -o bad@option' INT
726 kill -s INT $$
727
728
729 #### builtin.trap.exit.subshell.test
730 trap 'echo bye' EXIT
731 (echo hi)
732 echo $(echo hi)
733
734 ## STDOUT:
735 hi
736 hi
737 bye
738 ## END
739
740 #### builtin.trap.false.test
741 # https://www.spinics.net/lists/dash/msg01750.html
742 trap '(false) && echo BUG' INT
743 kill -s INT $$
744
745 ## stdout-json: ""
746
747 #### builtin.trap.kill.undef.test
748 trap 'echo derp' KILL
749 trap 'echo nevah' 9
750
751 ## stdout-json: ""
752
753 #### builtin.trap.nested.test
754 # https://www.spinics.net/lists/dash/msg01762.html
755 trap '(trap "echo exit" EXIT; :)' EXIT
756 ## STDOUT:
757 exit
758 ## END
759
760 #### builtin.trap.noexit.test
761 trap - 55
762 echo hi
763
764 ## STDOUT:
765 hi
766 ## END
767
768 #### builtin.trap.redirect.test
769 # Harald van Dijk <harald@gigawatt.nl> (2020-01-06) (list)
770 # Subject: EXIT trap handling in subshells broken
771 # To: DASH shell mailing list <dash@vger.kernel.org>
772 # Date: Mon, 06 Jan 2020 21:57:20 +0000
773
774 f() { (trap "echo $var" EXIT); }
775 var=bad
776 var=ok f
777
778 ## STDOUT:
779 ok
780 ## END
781
782 #### builtin.trap.return.test
783 # https://www.spinics.net/lists/dash/msg01792.html
784 trap 'f() { false; return; }; f; echo $?' EXIT
785 ## STDOUT:
786 1
787 ## END
788
789 #### builtin.trap.subshell.false.exit.test
790 trap "(false) && echo BUG" EXIT
791
792 ## status: 1
793 ## stdout-json: ""
794
795 #### builtin.trap.subshell.false.test
796 trap "(false) && echo BUG" INT; kill -s INT $$
797
798 ## stdout-json: ""
799
800 #### builtin.trap.subshell.loud2.test
801 # https://www.spinics.net/lists/dash/msg01766.html
802 trap 'set -o bad@option' INT; kill -s INT $$ && echo HUH
803 trap '(:; exit) && echo WEIRD' EXIT; false
804 ## STDOUT:
805 HUH
806 WEIRD
807 ## END
808
809 #### builtin.trap.subshell.loud.test
810 # https://www.spinics.net/lists/dash/msg01766.html
811 trap '(:; exit) && echo WEIRD' EXIT; false
812 ## STDOUT:
813 WEIRD
814 ## END
815
816 #### builtin.trap.subshell.quiet.test
817 # https://www.spinics.net/lists/dash/msg01755.html
818 (trap '(! :) && echo BUG1' EXIT)
819 (trap '(false) && echo BUG2' EXIT)
820 (trap 'readonly foo=bar; (foo=baz) && echo BUG3' EXIT)
821 (trap '(set -o bad@option) && echo BUG4' EXIT)
822 exit 0
823 ## stdout-json: ""
824
825 #### builtin.trap.subshell.true.ec1.test
826 # https://www.spinics.net/lists/dash/msg01761.html
827 trap '(true) || echo bug' EXIT; false
828
829 ## stdout-json: ""
830
831 #### builtin.trap.subshell.truefalse.test
832 # https://www.spinics.net/lists/dash/msg01750.html
833 trap '(false) && echo BUG' INT; kill -s INT $$
834 trap "(false) && echo BUG" EXIT
835 trap "(false); echo \$?" EXIT
836
837 ## STDOUT:
838 1
839 ## END
840
841 #### builtin.trap.supershell.test
842 trap 'echo bye' EXIT
843 (trap)
844 (trap 'echo so long' EXIT; trap)
845 (trap)
846
847 ## STDOUT:
848 trap -- 'echo bye' EXIT
849 trap -- 'echo so long' EXIT
850 so long
851 trap -- 'echo bye' EXIT
852 bye
853 ## END
854
855 #### builtin.unset.test
856 readonly x=foo
857 y=bar
858 unset y
859 echo ${y-unset}
860 echo ${x-error}
861 unset y
862 echo ${y-unset}
863 unset x
864
865 ## status: 1
866 ## STDOUT:
867 unset
868 foo
869 unset
870 ## END
871
872 #### parse.emptyvar.test
873 err=$($TEST_SHELL -c ': ${}' 2>&1 >/dev/null)
874 [ "$err" ]
875
876
877
878
879 #### parse.eval.error.test
880 cat >scr <<EOF
881 eval "if"
882 echo lived
883 EOF
884 $TEST_SHELL scr && exit 1
885 exit 0
886 ## stdout-json: ""
887
888 #### semantics.arith.assign.multi.test
889 : $((x = y = z = 0))
890 echo $x $y $z
891 ## STDOUT:
892 0 0 0
893 ## END
894
895 #### semantics.arithmetic.bool_to_num.test
896 [ $((5>=5)) -eq 1 ]
897
898
899 #### semantics.arithmetic.tilde.test
900 # bug found in POSIX testing (sh_05.ex tp357)
901
902 echo $((~10))
903 ## STDOUT:
904 -11
905 ## END
906
907 #### semantics.arith.modernish.test
908 # from https://github.com/modernish/modernish/blob/e3b66a8b68695265b9aebd43e1de1ab3fef66e57/lib/modernish/aux/fatal.sh
909 i=7
910 j=0
911 case $(( ((j+=6*i)==0x2A)>0 ? 014 : 015 )) in
912 ( 12 | 14 ) echo ok;; # OK or BUG_NOOCTAL
913 ( * ) echo fail; exit 1 ;;
914 esac
915 case $j in
916 ( 42 ) echo ok;; # BUG_NOOCTAL
917 ( * ) echo fail; exit 1;;
918 esac
919
920 ## STDOUT:
921 ok
922 ok
923 ## END
924
925 #### semantics.arith.pos.test
926 a=+47
927 [ $((a)) -eq 47 ]
928 echo $((a))
929 ## STDOUT:
930 47
931 ## END
932
933 #### semantics.arith.var.space.test
934 x=" 8"
935 y=$((x + 1))
936 echo $x $y
937
938 ## STDOUT:
939 8 9
940 ## END
941
942 #### semantics.assign.noglob.test
943 x='*'
944 echo "$x"
945
946 ## STDOUT:
947 *
948 ## END
949
950 #### semantics.assign.visible.test
951 set -e
952 x=5 y=$((x+2))
953 [ "$x" -eq 5 ]
954 # either x is treated as unset (and so y = 2) or not (and so y = 7)
955 [ "$y" -eq 2 ] || [ "$y" -eq 7 ]
956 echo ok
957 ## STDOUT:
958 ok
959 ## END
960
961 #### semantics.background.nojobs.stdin.test
962 cat >scr <<EOF
963 set +m
964 exec <in
965 cat &
966 wait
967 EOF
968
969 echo illegible >in
970 $TEST_SHELL scr
971
972
973 #### semantics.background.pid.test
974 echo 'echo $$ > pid.out' >showpid.sh
975 chmod +x showpid.sh
976 $TEST_SHELL showpid.sh &
977 sleep 1
978 [ "$!" -eq "$(cat pid.out)" ]
979
980 #### semantics.background.pipe.pid.test
981 echo 'echo $$ > pid.out' >showpid.sh
982 chmod +x showpid.sh
983 true | $TEST_SHELL showpid.sh &
984 sleep 1
985 [ "$!" -eq "$(cat pid.out)" ]
986
987 #### semantics.background.test
988 echo hi
989 { sleep 1 ; echo derp ; } &
990 echo bye
991 wait
992 ## STDOUT:
993 hi
994 bye
995 derp
996 ## END
997
998 #### semantics.backtick.exit.test
999 foo=$(trap 'echo bar' EXIT)
1000 echo $foo >&2
1001
1002 ## stdout-json: ""
1003
1004 #### semantics.backtick.fds.test
1005 set -e
1006 subshfds=$($TEST_UTIL/fds 0 20)
1007 $TEST_UTIL/fds 0 20
1008 echo $subshfds
1009
1010 ## STDOUT:
1011 0 open
1012 1 open
1013 2 open
1014 3 closed
1015 4 closed
1016 5 closed
1017 6 closed
1018 7 closed
1019 8 closed
1020 9 closed
1021 10 closed
1022 11 closed
1023 12 closed
1024 13 closed
1025 14 closed
1026 15 closed
1027 16 closed
1028 17 closed
1029 18 closed
1030 19 closed
1031 20 closed
1032 0 open 1 open 2 open 3 closed 4 closed 5 closed 6 closed 7 closed 8 closed 9 closed 10 closed 11 closed 12 closed 13 closed 14 closed 15 closed 16 closed 17 closed 18 closed 19 closed 20 closed
1033 ## END
1034
1035 #### semantics.backtick.ppid.test
1036 set -e
1037
1038 pid1=$($TEST_SHELL -c 'echo $PPID')
1039 echo $pid1 >pid1
1040
1041 $TEST_SHELL -c 'echo $PPID' >pid2
1042
1043 [ $(cat pid1) = $(cat pid2) ] || exit 2
1044 echo pid1=pid2
1045
1046 (echo $PPID) >ppid
1047 [ $PPID = $(cat ppid) ] || exit 3
1048 echo ppid=subshell
1049 ## STDOUT:
1050 pid1=pid2
1051 ppid=subshell
1052 ## END
1053
1054 #### semantics.case.ec.test
1055 # ADDTOPOSIX
1056
1057 (exit 3)
1058 echo $? # make sure we're making good ecs
1059 case a in
1060 ( b ) (exit 4) ;;
1061 ( * ) ;; # don't alter ec
1062 esac
1063 echo $? # should be 3
1064
1065 (exit 5)
1066 case a$(echo $?>ec) in # observe ec before entering case
1067 ( b ) (exit 6) ;;
1068 esac
1069 echo $?
1070 [ $(cat ec) = "5" ] || exit 2 # shouldn't have been altered yet!
1071
1072 # make sure the ec is actually visible
1073 false
1074 case a in
1075 ( a ) echo visible $? ;;
1076 esac
1077
1078 # but make sure that no match cases set the ec to 0
1079 false
1080 case a in
1081 ( b ) (exit 6) ;;
1082 esac
1083 echo $?
1084
1085
1086 ## STDOUT:
1087 3
1088 0
1089 0
1090 visible 1
1091 0
1092 ## END
1093
1094 #### semantics.case.escape.modernish.test
1095 # from https://github.com/modernish/modernish/blob/e3b66a8b68695265b9aebd43e1de1ab3fef66e57/lib/modernish/aux/fatal.sh
1096 case 'foo\
1097 bar' in
1098 ( foo\\"
1099 "bar ) echo good ;;
1100 ( * ) echo bad ;;
1101 esac
1102
1103 ## STDOUT:
1104 good
1105 ## END
1106
1107 #### semantics.case.escape.quotes.test
1108 foo=\"
1109 echo -n Literal: ''
1110 case "$foo" in
1111 \" ) echo OK ;;
1112 * ) echo NOT OK ;;
1113 esac
1114 echo -n Unquoted: ''
1115 case "$foo" in
1116 $foo ) echo OK ;;
1117 * ) echo NOT OK ;;
1118 esac
1119 echo -n Quoted: ''
1120 case "$foo" in
1121 "$foo" ) echo OK ;;
1122 * ) echo NOT OK ;;
1123 esac
1124
1125 ## STDOUT:
1126 Literal: OK
1127 Unquoted: OK
1128 Quoted: OK
1129 ## END
1130
1131 #### semantics.command.argv0.test
1132 set -e
1133
1134 explicit=$(${TEST_UTIL}/argv)
1135 [ "$explicit" = "argv[0] = \"${TEST_UTIL}/argv\";" ]
1136
1137 PATH="${TEST_UTIL}:$PATH"
1138 inpath=$(argv)
1139 [ "$inpath" = "argv[0] = \"argv\";" ]
1140 argv
1141
1142
1143 ## STDOUT:
1144 argv[0] = "argv";
1145 ## END
1146
1147 #### semantics.command-subst.newline.test
1148 # https://www.spinics.net/lists/dash/msg01844.html
1149 cat <<END
1150 1
1151 $(echo "")
1152 2
1153 END
1154 ## STDOUT:
1155 1
1156
1157 2
1158 ## END
1159
1160 #### semantics.command-subst.test
1161 x=$(false)
1162
1163 ## status: 1
1164
1165 #### semantics.-C.test
1166 echo >in <<EOF
1167 a one
1168 a two
1169 a one two three
1170 four
1171 EOF
1172
1173 touch out
1174
1175 set -o noclobber
1176 cat <in >out
1177 [ $? -gt 0 ] || exit 2
1178
1179 #### semantics.defun.ec.test
1180 # ADDTOPOSIX
1181 false
1182 f() { echo hi ; }
1183 echo $?
1184 f
1185
1186 false
1187 f() { echo hello ; }
1188 echo $?
1189 f
1190 ## STDOUT:
1191 0
1192 hi
1193 0
1194 hello
1195 ## END
1196
1197 #### semantics.dot.glob.test
1198 has_dot() {
1199 $TEST_UTIL/readdir | grep -e '^.$' >/dev/null
1200 }
1201
1202 has_dotdot() {
1203 $TEST_UTIL/readdir | grep -e '^..$' >/dev/null
1204 }
1205
1206 mkdir -p bar/inner
1207 touch bar/foo
1208 touch bar/inner/foo
1209 cd bar/inner
1210 echo .*/foo | sort # should be ../foo and ./foo
1211
1212 # some FS may be weird and not give these entries... simulate!
1213 has_dot || echo "./foo"
1214 has_dotdot || echo "../foo"
1215
1216 cd ../../
1217 rm -r bar
1218
1219 # this issue is under active discussion on the POSIX mailing list
1220
1221 # bash, dash, yash all work
1222 # fish, zsh fail
1223 ## STDOUT:
1224 ../foo ./foo
1225 ## END
1226
1227 #### semantics.errexit.carryover.test
1228 set -e
1229 putsn() { echo "$@"; }
1230 false && true
1231 putsn "It should be executed"
1232 false && true
1233 /bin/echo hello
1234
1235 ## STDOUT:
1236 It should be executed
1237 hello
1238 ## END
1239
1240 #### semantics.errexit.subshell.test
1241 set -o errexit
1242 if ( echo 1; false; echo 2; set -o errexit; echo 3; false; echo 4 ); then
1243 echo 5;
1244 fi
1245 echo 6 # This is executed because the subshell just returns false
1246 false
1247 echo 7
1248
1249 ## status: 1
1250 ## STDOUT:
1251 1
1252 2
1253 3
1254 4
1255 5
1256 6
1257 ## END
1258
1259 #### semantics.errexit.trap.test
1260 set -e; trap "false; echo BUG" USR1; kill -s USR1 $$
1261
1262 ## status: 1
1263
1264 #### semantics.error.noninteractive.test
1265 cat <<EOF > script
1266 unset x
1267 y=z
1268 echo ${x?z}
1269 echo blargh
1270 EOF
1271 chmod +x script
1272 $TEST_SHELL script
1273
1274 ## status: 1
1275
1276 #### semantics.escaping.backslash.modernish.test
1277 # from https://github.com/modernish/modernish/blob/e3b66a8b68695265b9aebd43e1de1ab3fef66e57/lib/modernish/aux/fatal.sh
1278 t=' :: \on\e :\tw'\''o \th\'\''re\e :\\'\''fo\u\r: : : '
1279 IFS=': '
1280 set -- ${t}
1281 IFS=''
1282 t=${#},${1-U},${2-U},${3-U},${4-U},${5-U},${6-U},${7-U},${8-U},${9-U},${10-U},${11-U},${12-U}
1283 case ${t} in
1284 ( '8,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,U,U,U,U' \
1285 | '9,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,,U,U,U' ) # QRK_IFSFINAL
1286 echo good ;;
1287 '8,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,U,U,U,U') echo weird;;
1288 ( * ) echo bad ; exit 1 ;;
1289 esac
1290
1291 ## STDOUT:
1292 good
1293 ## END
1294
1295 #### semantics.escaping.backslash.test
1296 printf '%s\t\n' > scr \
1297 'printf %s\\n foobar\|\&\;\<\>\(\)\$\`\\\"\'\''\ \?\*\[\'
1298 $TEST_SHELL scr
1299
1300
1301 ## STDOUT:
1302 foobar|&;<>()$`\"' ?*[
1303 ## END
1304
1305 #### semantics.escaping.heredoc.dollar.test
1306 cat <<EOF
1307 echo \\\$var
1308 EOF
1309 cat <<'EOF'
1310 echo \\\$var
1311 EOF
1312
1313 ## STDOUT:
1314 echo \$var
1315 echo \\\$var
1316 ## END
1317
1318 #### semantics.escaping.newline.test
1319 printf '%s' '\\'n
1320 printf '%s' "\n"
1321 printf "\n"
1322 printf '\n'
1323 printf '\\n'
1324
1325 ## stdout-json: "\\\\n\\n\n\n\\n"
1326
1327 #### semantics.escaping.quote.test
1328 set -e
1329
1330 for c in '"' '#' '%' '&' "'" '(' ')' '*' '+' ',' '-' '.' '/' ':' \
1331 ';' '<' '=' '>' '?' '@' '[' ']' '^' '_' '{' '|' '}' '~' ' '
1332 do
1333 cat >script <<EOF
1334 x=\`printf '%s' \\$c\`; printf '%s\\n' "\$x"
1335 EOF
1336 echo "$c"
1337 $TEST_SHELL script >out
1338 [ $? -eq 0 ] && [ "$c" = "$(cat out)" ]
1339 done
1340 echo done
1341 ## STDOUT:
1342 "
1343 #
1344 %
1345 &
1346 '
1347 (
1348 )
1349 *
1350 +
1351 ,
1352 -
1353 .
1354 /
1355 :
1356 ;
1357 <
1358 =
1359 >
1360 ?
1361 @
1362 [
1363 ]
1364 ^
1365 _
1366 {
1367 |
1368 }
1369 ~
1370
1371 done
1372 ## END
1373
1374 #### semantics.escaping.single.test
1375 # cf tp399
1376 cat <<weirdo
1377 line one
1378 line two
1379 "line".\${PATH}.\'three\'\\x\
1380 line four
1381 weirdo
1382
1383 ## STDOUT:
1384 line one
1385 line two
1386 "line".${PATH}.\'three\'\xline four
1387 ## END
1388
1389 #### semantics.eval.makeadder.test
1390 makeadder() {
1391 eval "adder() { echo \$((\$1 + $1)) ; }"
1392 }
1393
1394 makeadder 5
1395 adder 1
1396 makeadder 10
1397 adder 1
1398
1399 ## STDOUT:
1400 6
1401 11
1402 ## END
1403
1404 #### semantics.evalorder.fun.test
1405 # bash: assign
1406 # yash, dash, smoosh: redir
1407 # ADDTOPOSIX
1408 show() { echo "got ${EFF-unset}"; }
1409 unset x
1410 EFF=${x=assign} show 2>${x=redir}
1411 echo ${EFF-unset after function call}
1412 [ -f assign ] && echo assign exists && rm assign
1413 [ -f redir ] && echo redir exists && rm redir
1414
1415 ## STDOUT:
1416 got redir
1417 unset after function call
1418 redir exists
1419 ## END
1420
1421 #### semantics.expansion.heredoc.backslash.test
1422 cat <<EOF
1423 an escaped \\[bracket]
1424 should \\ work just fine
1425 EOF
1426 cat <<EOF
1427 exit \$?
1428 EOF
1429 ## STDOUT:
1430 an escaped \[bracket]
1431 should \ work just fine
1432 exit $?
1433 ## END
1434
1435 #### semantics.expansion.quotes.adjacent.test
1436 mkdir a
1437 touch a/b
1438 touch a/c
1439 echo a/*
1440 echo "a"/*
1441 echo 'a'/*
1442 mkdir "foo*["
1443 touch "foo*["/weird
1444 touch "foo*["/wild
1445 touch "foo*["/crazy
1446 echo "foo*["/*
1447 echo "foo*["/[wz]*
1448 ## STDOUT:
1449 a/b a/c
1450 a/b a/c
1451 a/b a/c
1452 foo*[/crazy foo*[/weird foo*[/wild
1453 foo*[/weird foo*[/wild
1454 ## END
1455
1456 #### semantics.expansion.substring.test
1457 FOO="\\a"
1458 echo ${FOO#*\\}
1459
1460 ## STDOUT:
1461 a
1462 ## END
1463
1464 #### semantics.for.readonly.test
1465 # ADDTOPOSIX
1466 (for x in a b c; do echo $x; readonly x; done) && exit 1
1467 exit 0
1468
1469 ## STDOUT:
1470 a
1471 ## END
1472
1473 #### semantics.fun.error.restore.test
1474 set -u
1475
1476 f() {
1477 echo $1
1478 echo <none
1479 }
1480
1481 set -- a b c
1482 f arg1 arg2
1483 printf '<%s>\n' "$@"
1484
1485 ## STDOUT:
1486 arg1
1487 <a>
1488 <b>
1489 <c>
1490 ## END
1491
1492 #### semantics.-h.nonposix.test
1493 set -h
1494 hash -r
1495 f() {
1496 ls
1497 touch hi
1498 rm hi
1499 }
1500 hash
1501 hash | grep ls || exit 1
1502 hash | grep touch || exit 2
1503 hash | grep rm || exit 3
1504
1505
1506
1507 #### semantics.ifs.combine.ws.test
1508 unset IFS
1509 echo > spaced
1510 printf "%b" '\tx' >> spaced
1511 echo >> spaced
1512 echo " 5" >> spaced
1513 printf '%b' ' 12\t ' >> spaced
1514 echo `cat spaced`
1515 IFS=$(printf '%b' ' \n\t')
1516 echo `cat spaced`
1517 ## STDOUT:
1518 x 5 12
1519 x 5 12
1520 ## END
1521
1522 #### semantics.kill.traps.test
1523 trap "echo hi" TERM
1524 sleep 10 &
1525 pid=$!
1526 sleep 1
1527 kill $pid
1528 [ "$?" -eq 0 ] || exit 1
1529 sleep 1
1530 wait $pid
1531 [ "$?" -ge 128 ] || exit 2
1532
1533
1534 ## stdout-json: ""
1535
1536 #### semantics.length.test
1537 # https://www.spinics.net/lists/dash/msg01749.html
1538 v=abc; echo ab${#v}cd
1539
1540 ## STDOUT:
1541 ab3cd
1542 ## END
1543
1544 #### semantics.monitoring.ttou.test
1545 # id:20201221162442.GA26001@stack.nl
1546 # Jilles Tjoelker <jilles@stack.nl> (2020-12-21) (list)
1547 # Subject: Re: dash 0.5.11.2, busybox sh 1.32.0, FreeBSD 12.2 sh: spring TTOU but should not i think
1548 # To: Harald van Dijk <harald@gigawatt.nl>
1549 # Cc: Steffen Nurpmeso <steffen@sdaoden.eu>, DASH shell mailing list <dash@vger.kernel.org>, Denys Vlasenko <vda.linux@googlemail.com>
1550 # Date: Mon, 21 Dec 2020 17:24:42 +0100
1551
1552 $TEST_SHELL -c "( $TEST_SHELL -c 'trap echo\ TTOU TTOU; set -m; echo all good' )"
1553
1554 ## STDOUT:
1555 all good
1556 ## END
1557
1558 #### semantics.no-command-subst.test
1559 false ; x=hi
1560
1561
1562 #### semantics.noninteractive.expansion.exit.test
1563 unset x
1564 echo ${x?alas, poor yorick}
1565
1566 ## status: 1
1567
1568 #### semantics.pattern.bracket.quoted.test
1569 # from https://github.com/modernish/modernish/blob/e3b66a8b68695265b9aebd43e1de1ab3fef66e57/lib/modernish/aux/fatal.sh
1570 t='ab]cd'
1571 case c in
1572 ( *["${t}"]* )
1573 case e in
1574 ( *[!"${t}"]* ) echo OK;;
1575 ( * ) echo FAILED inner ;;
1576 esac ;;
1577 ( * ) echo FAILED outer ;;
1578 esac
1579
1580 case \" in
1581 ( *["${t}"]* ) echo QUOTED ;;
1582 ( * ) echo UNQUOTED ;;
1583 esac
1584
1585 ## STDOUT:
1586 OK
1587 UNQUOTED
1588 ## END
1589
1590 #### semantics.pattern.hyphen.test
1591 touch file-
1592 touch filea
1593
1594 echo file[-123]
1595 echo file[123-]
1596 echo file[[.-.]]
1597 echo file[[=-=]]
1598 echo file[!-123]
1599 echo file[[:alpha:]]
1600 echo file[a-z]
1601 ## STDOUT:
1602 file-
1603 file-
1604 file-
1605 file-
1606 filea
1607 filea
1608 filea
1609 ## END
1610
1611 #### semantics.pattern.modernish.test
1612 # from https://github.com/modernish/modernish/blob/e3b66a8b68695265b9aebd43e1de1ab3fef66e57/lib/modernish/aux/fatal.sh
1613 t=' :: \on\e :\tw'\''o \th\'\''re\e :\\'\''fo\u\r: : : '
1614 IFS=': '
1615 set -- ${t}
1616 IFS=''
1617 t=${#},${1-U},${2-U},${3-U},${4-U},${5-U},${6-U},${7-U},${8-U},${9-U},${10-U},${11-U},${12-U}
1618 printf "%s\n" "$t"
1619 case ${t} in
1620 ( '8,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,U,U,U,U' \
1621 | '9,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,,U,U,U' ) # QRK_IFSFINAL
1622 echo good ;;
1623 '8,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,U,U,U,U') echo weird;;
1624 ( * ) echo bad ; exit 1 ;;
1625 esac
1626
1627
1628 #### semantics.pattern.rightbracket.test
1629 touch file]
1630 touch filea
1631
1632 echo file[]123]
1633 echo file[[.].]]
1634 echo file[[=]=]]
1635 echo file[!]123]
1636 echo file[[:alpha:]]
1637 echo file[a-z]
1638 ## STDOUT:
1639 file]
1640 file]
1641 file]
1642 filea
1643 filea
1644 filea
1645 ## END
1646
1647 #### semantics.pipe.chained.test
1648 c="echo works"
1649 for n in $(seq 1 10)
1650 do
1651 c="$c | { read x; echo \$x; }"
1652 done
1653
1654 eval $c 2>err
1655 [ -e err ] && ! [ -s err ] || exit 2
1656
1657 ## STDOUT:
1658 works
1659 ## END
1660
1661 #### semantics.quote.backslash.test
1662 echo []
1663 echo '\[]'
1664 echo "\[]"
1665
1666 ## STDOUT:
1667 []
1668 \[]
1669 \[]
1670 ## END
1671
1672 #### semantics.quote.tilde.test
1673 echo "~"
1674 ## STDOUT:
1675 ~
1676 ## END
1677
1678 #### semantics.redir.close.test
1679 # https://www.spinics.net/lists/dash/msg01775.html
1680 { exec 8</dev/null; } 8<&-; : <&8 && echo "oops, still open"
1681
1682 ## status: 1
1683 ## stdout-json: ""
1684
1685 #### semantics.redir.fds.test
1686 $TEST_UTIL/fds
1687 exec 3>&1
1688 $TEST_UTIL/fds
1689
1690 ## STDOUT:
1691 0 open
1692 1 open
1693 2 open
1694 3 closed
1695 4 closed
1696 5 closed
1697 6 closed
1698 7 closed
1699 8 closed
1700 9 closed
1701 0 open
1702 1 open
1703 2 open
1704 3 open
1705 4 closed
1706 5 closed
1707 6 closed
1708 7 closed
1709 8 closed
1710 9 closed
1711 ## END
1712
1713 #### semantics.redir.from.test
1714 set -e
1715 echo hi >file
1716 [ -s file ]
1717 read x <file
1718 [ "$x" = "hi" ]
1719 rm file
1720
1721 #### semantics.redir.indirect.test
1722 f() {
1723 echo message >&2
1724 }
1725
1726 msg=$(f 2>&1)
1727 [ "$msg" = "message" ] || exit 1
1728
1729 unset msg
1730 x=1
1731 msg=$(f 2>&$x)
1732 [ "$msg" = "message" ] || exit 2
1733
1734 echo ok
1735 ## STDOUT:
1736 ok
1737 ## END
1738
1739 #### semantics.redir.nonregular.test
1740 set -C
1741 : >/dev/null || exit 2
1742 echo ok
1743
1744 ## STDOUT:
1745 ok
1746 ## END
1747
1748 #### semantics.redir.toomany.test
1749 c="echo hi"
1750 for n in $(seq 3 10)
1751 do
1752 c="{ $c; echo hi; } >file_$n"
1753 done
1754
1755 eval $c 2>err
1756 [ -e err ] && ! [ -s err ] || exit 2
1757
1758 rm file_* err
1759
1760 MAX=$(ulimit >/dev/null 2>&1 && ulimit -n 2>/dev/null || echo 10000)
1761
1762 # don't even bother if the FD limit is too high (256 on some macOS)
1763 [ "$MAX" -lt 300 ] || exit 0
1764
1765 c="echo hi"
1766 for n in $(seq 3 $MAX)
1767 do
1768 c="{ $c; echo hi; } >file_$n"
1769 done
1770
1771 eval $c 2>err
1772 [ -s err ] || exit 3
1773 rm file_*
1774
1775 #### semantics.redir.to.test
1776 set -e
1777 echo hi >file
1778 [ -s file ]
1779 [ "$(cat file)" = "hi" ]
1780 rm file
1781
1782 #### semantics.return.trap.test
1783 # Robert Elz <kre@munnari.OZ.AU> (2020-03-16) (inbox list unread)
1784 # Subject: Re: XCU: 'exit' trap condition [was:Re: XCU: 'return' from subshell]
1785 # To: Joerg Schilling <Joerg.Schilling@fokus.fraunhofer.de>
1786 # Cc: fieldhouse@gmx.net, austin-group-l@opengroup.org
1787 # Date: Mon, 16 Mar 2020 22:15:10 +0700
1788
1789 f() ( trap "echo FOO" EXIT; return 5; echo BAR )
1790 f
1791
1792 ## STDOUT:
1793 FOO
1794 ## END
1795
1796 #### semantics.simple.link.test
1797 set -e
1798 echo 'echo hi' >cmd.sh
1799 chmod +x cmd.sh
1800 ln -s cmd.sh link.sh
1801 OLDPATH=$PATH
1802 PATH=.
1803 [ -x cmd.sh ]
1804 [ -L link.sh ]
1805 cmd.sh # command works
1806 link.sh # symlink works
1807 PATH=$OLDPATH
1808 ls
1809 rm cmd.sh link.sh
1810 ## STDOUT:
1811 hi
1812 hi
1813 cmd.sh
1814 link.sh
1815 ## END
1816
1817 #### semantics.slash.glob.test
1818 arg_len() {
1819 echo $#
1820 }
1821
1822 trap 'rm -r foo' EXIT
1823
1824 mkdir foo
1825 touch foo/a foo/b foo/c
1826 [ "$(arg_len foo//*)" -eq 3 ] && echo OK
1827
1828 ## STDOUT:
1829 OK
1830 ## END
1831
1832 #### semantics.special.assign.visible.nonposix.test
1833 x=5 y=$((x+2)) :
1834 echo $x $y
1835
1836 ## STDOUT:
1837 5 7
1838 ## END
1839
1840 #### semantics.splitting.ifs.test
1841 cat << EOF > input
1842 -,1-,-2,-,3,-
1843 EOF
1844
1845 IFS="-,"
1846 echo `cat input`
1847 ## STDOUT:
1848 1 2 3
1849 ## END
1850
1851 #### semantics.subshell.background.traps.test
1852 (trap - INT; echo INT sleeping...; sleep 10; echo INT awake) & pid=$!
1853 sleep 1
1854 kill $pid
1855 wait $pid
1856 ec=$?
1857 [ "$ec" -ge 128 ] || exit 1
1858 (trap - QUIT; echo QUIT sleeping...; sleep 10; echo QUIT awake) & pid=$!
1859 sleep 1
1860 kill -QUIT $pid
1861 wait $pid
1862 ec=$?
1863 [ "$ec" -ge 128 ] || exit 2
1864 ## STDOUT:
1865 INT sleeping...
1866 QUIT sleeping...
1867 ## END
1868
1869 #### semantics.subshell.break.test
1870 # https://www.spinics.net/lists/dash/msg01773.html
1871 for x in a b
1872 do
1873 (
1874 for y in c d
1875 do
1876 break 2
1877 done
1878 echo $x
1879 )
1880 done
1881 ## STDOUT:
1882 a
1883 b
1884 ## END
1885
1886 #### semantics.subshell.redirect.test
1887 # Ensure that the exit trap is ran with the redirections still active.
1888 (trap 'echo foo' EXIT) >/dev/null
1889
1890 ## stdout-json: ""
1891
1892 #### semantics.subshell.return2.test
1893 # Dirk Fieldhouse <fieldhouse@gmx.net> (2020-03-11) (junk list)
1894 # Subject: Re: XCU: 'return' from subshell
1895 # To: Austin Group <austin-group-l@opengroup.org>
1896 # Cc: chet.ramey@case.edu, Robert Elz <kre@munnari.OZ.AU>
1897 # Date: Wed, 11 Mar 2020 14:49:31 +0000
1898
1899 f1() {
1900 ( echo foo; return )
1901 echo bar
1902 }
1903
1904 f1
1905 ## STDOUT:
1906 foo
1907 bar
1908 ## END
1909
1910 #### semantics.subshell.return.test
1911 # Stephane Chazelas <stephane@chazelas.org> (2020-03-11) (list)
1912 # Subject: Re: XCU: 'return' from subshell
1913 # To: Robert Elz <kre@munnari.OZ.AU>
1914 # Cc: Dirk Fieldhouse <fieldhouse@gmx.net>, Austin Group <austin-group-l@opengroup.org>
1915 # Date: Wed, 11 Mar 2020 06:37:41 +0000
1916
1917 f() { (return 42; echo x); echo "$?"; }; f
1918
1919 ## STDOUT:
1920 42
1921 ## END
1922
1923 #### semantics.substring.quotes.test
1924 FOO="a?b"
1925 [ "${FOO#*"?"}" = b ] && echo OK1
1926 FOO="abc"
1927 [ "${FOO#"${FOO%???}"}" = "$FOO" ] && echo OK2
1928
1929 ## STDOUT:
1930 OK1
1931 OK2
1932 ## END
1933
1934 #### semantics.tilde.colon.test
1935 tilde=~
1936 cat << EOF >test_script
1937 var=:~
1938 [ "\$var" = ":$tilde" ]
1939 EOF
1940 chmod +x test_script
1941 $TEST_SHELL test_script
1942
1943 #### semantics.tilde.no-exp.test
1944 echo hi:~
1945 x=:
1946 echo hello${x}~
1947
1948 ## STDOUT:
1949 hi:~
1950 hello:~
1951 ## END
1952
1953 #### semantics.tilde.quoted.prefix.test
1954 # ADDTOPOSIX
1955
1956 set -e
1957 tilde=$(echo ~)
1958 [ "$tilde" = "$HOME" ] || exit 1
1959
1960 funny='~'\""$LOGNAME"\"
1961 exp=$(eval "echo $funny")
1962 [ "$exp" = "~$LOGNAME" ] || exit 2
1963
1964 [ ~/ = "$HOME"/ ] || exit 3
1965
1966 echo ok
1967 ## STDOUT:
1968 ok
1969 ## END
1970
1971 #### semantics.tilde.quoted.test
1972 HOME="weird times"
1973 printf '%s\n' ~
1974 touch a1 a2 a3
1975 HOME='a*'
1976 printf '%s\n' ~
1977
1978 ## STDOUT:
1979 weird times
1980 a*
1981 ## END
1982
1983 #### semantics.tilde.sep.test
1984 # ADDTOPOSIX
1985 [ ~: = "~:" ] || exit 1
1986
1987 y=~
1988 [ $y = "$HOME" ] || exit 2
1989
1990 y=~/foo
1991 [ $y = "$HOME/foo" ] || exit 3
1992
1993 y=~:foo
1994 [ $y = "$HOME:foo" ] || exit 4
1995
1996 y=foo:~
1997 [ $y = "foo:$HOME" ] || exit 5
1998
1999 y=foo:~:bar
2000 [ $y = "foo:$HOME:bar" ] || exit 6
2001
2002 echo ok
2003 ## STDOUT:
2004 ok
2005 ## END
2006
2007 #### semantics.tilde.test
2008 echo ~ >tilde.out
2009 var=~
2010 echo $var > var.out
2011 [ -f tilde.out ] && [ -f var.out ] && \
2012 [ -s tilde.out ] && [ -s var.out ] && \
2013 [ $(cat tilde.out) = $(cat var.out) ] && \
2014 [ $(cat tilde.out) != "~" ]
2015
2016
2017
2018 #### semantics.traps.async.test
2019 (
2020 kill -s QUIT $($TEST_SHELL -c 'echo $PPID') || exit 1
2021 echo done
2022 ) &
2023 wait $!
2024
2025 ## STDOUT:
2026 done
2027 ## END
2028
2029 #### semantics.traps.inherit.test
2030 (
2031 trap "echo got SIGINT" INT
2032
2033 # default trap will mean we actually get a QUIT, overriding the default on asyncs
2034 trap - QUIT
2035
2036 mypid=$($TEST_SHELL -c 'echo $PPID')
2037
2038 # this can be overridden
2039 kill -s INT "$mypid" || exit 4
2040
2041 # will kill this shell,
2042 echo "sending SIGQUIT"
2043 kill -s QUIT "$mypid" || exit 2
2044 exit 0
2045 ) &
2046 wait $!
2047 echo $?
2048
2049
2050 ## STDOUT:
2051 got SIGINT
2052 sending SIGQUIT
2053 131
2054 ## END
2055
2056 #### semantics.var.alt.nullifs.test
2057 IFS=
2058 printf '<%s>\n' ${x+uhoh} a b
2059
2060 f() { echo $#; printf '<%s>\n' "$@" ; }
2061 f ${x+uhoh} a b
2062
2063 x=hi
2064 f ${x+uhoh} a b
2065
2066
2067 ## STDOUT:
2068 <a>
2069 <b>
2070 2
2071 <a>
2072 <b>
2073 3
2074 <uhoh>
2075 <a>
2076 <b>
2077 ## END
2078
2079 #### semantics.var.alt.null.test
2080 f() { echo $# ; }
2081 unset -v nonesuch
2082 f ${nonesuch+nonempty} a b
2083
2084 x=foo
2085 f ${x+hi} a b
2086
2087 ## STDOUT:
2088 2
2089 3
2090 ## END
2091
2092 #### semantics.varassign.test
2093 # https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=a29e9a1738a4e7040211842f3f3d90e172fa58ce
2094 foo=bar; echo ${foo=BUG}; echo $foo
2095
2096 ## STDOUT:
2097 bar
2098 bar
2099 ## END
2100
2101 #### semantics.var.builtin.nonspecial.test
2102 # successful command
2103 unset x
2104 x=value command alias >/dev/null 2>&1
2105 echo ${x-unset}
2106 test -z "$x" || exit 1
2107
2108 # unsuccessful command
2109 unset x
2110 x=value command alias -: >/dev/null 2>&1
2111 echo ${x-unset}
2112 test -z "$x" || exit 2
2113
2114 ## STDOUT:
2115 unset
2116 unset
2117 ## END
2118
2119 #### semantics.var.dashu.test
2120 unset nonesuch
2121 $TEST_SHELL -u -c 'echo $nonesuch' && exit 1
2122 $TEST_SHELL -u -c 'echo $3' && exit 1
2123 $TEST_SHELL -u -c 'var=val ; echo ${var+$nonesuch}' && exit 1
2124 $TEST_SHELL -u -c 'echo $(($nonesuch + 1))' && exit 1
2125 $TEST_SHELL -u -c 'echo $((nonesuch + 1))' && exit 1
2126 $TEST_SHELL -u -c 'echo ${#nonesuch}' && exit 1
2127 echo passed
2128
2129 ## STDOUT:
2130 passed
2131 ## END
2132
2133 #### semantics.var.format.tilde.test
2134 unset x
2135 tilde=~
2136 : ${x:=~}
2137 ext=~/foo
2138 [ "$x" = "$tilde" ] && \
2139 [ "/foo" = ${ext#~} ] && \
2140 ! $TEST_SHELL -c 'echo ${y?~}'
2141
2142 #### semantics.variable.escape.length.test
2143 x=\n
2144 echo ${#x}
2145 x=\\n
2146 echo ${#x}
2147
2148 ## STDOUT:
2149 1
2150 2
2151 ## END
2152
2153 #### semantics.var.ifs.sep.test
2154 IFS=", "
2155 set 1 2 3
2156 echo "$*"
2157
2158 ## STDOUT:
2159 1,2,3
2160 ## END
2161
2162 #### semantics.var.star.emptyifs.test
2163 IFS=""
2164 bee="b e e"
2165 set a "$bee" c
2166
2167 printf '<%s>\n' $*
2168 printf '<%s>\n' HI$*BYE
2169
2170 ## STDOUT:
2171 <a>
2172 <b e e>
2173 <c>
2174 <HIa>
2175 <b e e>
2176 <cBYE>
2177 ## END
2178
2179 #### semantics.var.star.format.test
2180 sp="s p aces"
2181 tn=$(printf '%b' 'and\ttabs\n and newlines')
2182 set -- a "$sp" b c "$tn"
2183 IFS=": "
2184 printf '<%s>\n' "${var=$*}"
2185 unset var
2186 unset IFS
2187 printf '<%s>\n' "${var=$*}"
2188
2189 ## STDOUT:
2190 <a:s p aces:b:c:and tabs
2191 and newlines>
2192 <a s p aces b c and tabs
2193 and newlines>
2194 ## END
2195
2196 #### semantics.var.unset.nofield.test
2197 count() { echo $#; }
2198 [ $(count a $nonesuch b) -eq 2 ]
2199
2200 #### semantics.wait.alreadydead.test
2201 sleep 10 &
2202 pid=$!
2203 sleep 1
2204 kill $pid
2205 echo kill ec: $?
2206 sleep 1
2207 wait $pid
2208 echo wait ec: $?
2209
2210 ## STDOUT:
2211 kill ec: 0
2212 wait ec: 143
2213 ## END
2214
2215 #### semantics.while.test
2216 i=0
2217 while [ $i -lt 10 ]
2218 do
2219 i=$((i + 1))
2220 echo $i
2221 done
2222 echo $?
2223 i=0
2224 while [ $i -lt 10 ]
2225 do
2226 i=$((i + 1))
2227 echo $i;
2228 false
2229 done
2230 echo $?
2231
2232 ## STDOUT:
2233 1
2234 2
2235 3
2236 4
2237 5
2238 6
2239 7
2240 8
2241 9
2242 10
2243 0
2244 1
2245 2
2246 3
2247 4
2248 5
2249 6
2250 7
2251 8
2252 9
2253 10
2254 1
2255 ## END
2256
2257 #### sh.-c.arg0.test
2258 cat > scr <<EOF
2259 echo "i am \$0, hear me roar"
2260 EOF
2261 $TEST_SHELL -c '. "$0"' ./scr
2262 ## STDOUT:
2263 i am ./scr, hear me roar
2264 ## END
2265
2266 #### sh.env.ppid.test
2267 $TEST_SHELL -c 'echo $PPID' >ppid
2268 inner=$(cat ppid)
2269 rm ppid
2270 [ "$inner" -eq "$$" ]
2271
2272
2273
2274 #### sh.file.weirdness.test
2275 $TEST_SHELL nonesuch
2276 echo 'echo works' >scr
2277 $TEST_SHELL scr
2278 $TEST_SHELL ./scr
2279 echo 'echo nope' >scr
2280 chmod -r scr
2281 $TEST_SHELL ./scr && exit 1
2282 $TEST_SHELL scr && exit 1
2283 rm -f scr
2284
2285
2286 ## STDOUT:
2287 works
2288 works
2289 ## END
2290
2291 #### sh.monitor.bg.test
2292 set -m
2293
2294 start=$(date "+%s")
2295 sleep 3 & pid=$!
2296 kill -TSTP $pid
2297 jobs -l
2298 stop=$(date "+%s")
2299 elapsed=$((stop - start))
2300 echo $stop - $start = $elapsed
2301 [ $((elapsed)) -lt 2 ] || exit 1
2302
2303 jobs -l
2304 bg >output
2305
2306 stop2=$(date "+%s")
2307 elapsed=$((stop2 - start))
2308 echo $stop2 - $start = $elapsed
2309 [ $((elapsed)) -lt 2 ] || exit 2
2310 grep "[1]" output || exit 3
2311 grep "sleep 3" output || exit 4
2312
2313 wait
2314
2315 stop3=$(date "+%s")
2316 elapsed=$((stop3 - start))
2317 echo $stop3 - $start = $elapsed
2318 [ $((elapsed)) -ge 3 ] || exit 5
2319
2320
2321 #### sh.monitor.fg.test
2322 set -m
2323
2324 start=$(date "+%s")
2325 sleep 3 & pid=$!
2326 kill -TSTP $pid
2327 jobs -l
2328 stop=$(date "+%s")
2329 elapsed=$((stop - start))
2330 echo $stop - $start = $elapsed
2331 [ $((elapsed)) -lt 2 ] || exit 1
2332
2333 jobs -l
2334 fg >output
2335
2336 stop2=$(date "+%s")
2337 elapsed=$((stop2 - start))
2338 echo $stop2 - $start = $elapsed
2339 [ $((elapsed)) -ge 3 ] || exit 2
2340 grep "sleep 3" output || exit 3
2341
2342
2343 #### sh.set.ifs.test
2344 cat >show_ifs <<EOF
2345 printf '%s' "$IFS"
2346 EOF
2347 $TEST_SHELL show_ifs || exit 1
2348 export IFS=123
2349 $TEST_SHELL show_ifs || exit 1
2350 IFS=abc $TEST_SHELL show_ifs || exit 1
2351
2352 ## STDOUT:
2353
2354
2355
2356 ## END
2357