1
1
#!/bin/echo no
2
2
3
- # TODO: categorize tests
4
-
5
- # TODO https://mywiki.wooledge.org/BashFAQ
6
- # http://tiswww.case.edu/php/chet/bash/FAQ
7
- # https://mywiki.wooledge.org/BashPitfalls#set_-euo_pipefail
8
-
9
- # // ${#} ${#x} ${#@} ${#x[@]} ${#!} ${!#}
10
- # // ${!} ${!@} ${!@Q} ${!x} ${!x@} ${!x@Q} ${!x#} ${!x[} ${!x[*]}
11
-
12
- # Looked like a prefix but wasn't: three chars (@ # -) are both paremeter name
13
- # and slice operator. When immediately followed by } it's parameter, otherwise
14
- # we did NOT have a prefix and it's an operator.
15
- #
16
- # ${#-} ${#-abc}
17
- # ${##} ${##0}
18
- # ${#@} ${#@Q}
19
- #
20
- # backslash not discarded: echo "abc\"def"
21
-
22
- # ${x:-y} use default
23
- # ${x:=y} assign default (error if positional)
24
- # ${x:?y} err if null
25
- # ${x:+y} alt value
26
- # ${x:off} ${x:off:len} off<0 from end (must ": -"), len<0 also from end must
27
- # 0-based indexing
28
- # ${@:off:len} positional parameters, off -1 = len, -len is error
29
- # 1-based indexing
30
-
31
- # [] wins over +()
32
- # touch 'AB[DEF]'; echo AB[+(DEF]) AB[+(DEF)?
33
- # AB[+(DEF]) AB[DEF]
34
-
35
- # Testing shell corner cases _within_ a shell script is kind of hard.
36
-
37
3
[ -f testing.sh ] && . testing.sh
38
4
39
5
# TODO make fake pty wrapper for test infrastructure
40
6
41
- #testing "name" "command" "result" "infile" "stdin"
7
+ # testing "name" "command" "result" "infile" "stdin"
8
+ # texpect "name" "command" [R]I/O/E"string" X[ERR]
42
9
43
- # texpect "name" "command" E/O/I"string"
44
-
45
- # Use "bash" name for host, "sh" for toybox
10
+ # Use "bash" name for host, "sh" for toybox. (/bin/sh is often defective.)
46
11
[ -z "$SH" ] && { [ -z "$TEST_HOST" ] && SH="sh" || export SH="bash" ; }
47
- # Prompt changes for root/ normal user
48
- [ $(id -u) -eq 0 ] && P='# ' || P='$ '
49
- # run sufficiently isolated shell child process to get predictable results
12
+ # The expected prompt is different for root vs normal user
13
+ [ $UID -eq 0 ] && P='# ' || P='$ '
14
+ # insulate shell child process to get predictable results
50
15
SS="env -i PATH=${PATH@Q} PS1='\\$ ' $SH --noediting --noprofile --norc -is"
51
16
17
+ # Wrap txpect for shell testing
52
18
shxpect() {
53
19
X="$1"
54
20
shift
@@ -57,10 +23,11 @@ shxpect() {
57
23
58
24
shxpect "prompt and exit" I$'exit\n'
59
25
shxpect "prompt and echo" I$'echo hello\n' O$'hello\n' E"$P"
26
+ shxpect "redir" I$'cat<<<hello\n' O$'hello\n' E"$P"
60
27
shxpect "redirect err" I$'echo > /dev/full\n' E E"$P" X1
61
28
shxpect "wait for <(exit)" I$'cat <(echo hello 1>&2)\n' E$'hello\n' E"$P"
62
29
63
- # Test the sh -c stuff before changing EVAL
30
+ # Test shell command line ( -c and how scripts run) before changing EVAL
64
31
testing '-c "" exit status 0' '$SH -c "" && echo $?' '0\n' '' ''
65
32
testing '-c args' "\$SH -c 'echo \$0,\$1,\$2,\$3' one two three four five" \
66
33
"one,two,three,four\n" "" ""
@@ -72,6 +39,12 @@ testing '-c arg split2' \
72
39
"$SH -c 'for i in a\"\$* \$@\"b; do echo =\$i=;done' one two three four five"\
73
40
"=atwo three four five two=\n=three=\n=four=\n=fiveb=\n" "" ""
74
41
testing '-c arg count' "$SH -c 'echo \$#' 9 8 7 6 1 2 3 4" "7\n" "" ""
42
+ testing 'trailing \' "$SH -c 'echo \'" '\\\n' '' ''
43
+ testing "trailing \\ in ''" "$SH -c \$'echo \\'one\\\\\\ntwo\\''" \
44
+ 'one\\\ntwo\n' '' ''
45
+ testing 'trailing \ in ""' "$SH -c \$'echo \"one\\\\\\ntwo\"'" 'onetwo\n' \
46
+ '' ''
47
+ testing 'vanishing \' "$SH -c \$'echo \\\\\\n a'" 'a\n' '' ''
75
48
testing "exec3" '$C -c "{ exec readlink /proc/self/fd/0;} < /proc/self/exe"' \
76
49
"$(readlink -f $C)\n" "" ""
77
50
testing 'arg shift' "$SH -c '"'for i in "" 2 1 1 1; do echo $? $1; shift $i; done'"' one two three four five" \
@@ -121,6 +94,8 @@ testing "eval0" "$SH -c 'eval echo \$*' one two three" "two three\n" "" ""
121
94
# Change EVAL to call sh -c for us, using "bash" explicitly for the host.
122
95
export EVAL="timeout 10 $SH -c"
123
96
97
+ # From here on, tests run within the new shell by default.
98
+
124
99
testing 'return code' 'if false; then echo true; fi; echo $?' '0\n' '' ''
125
100
testing 'return code 2' 'if true; then false; fi; echo $?' '1\n' '' ''
126
101
testing 'return code 3' 'x=0; while [ $((x++)) -lt 2 ]; do echo $x; done; echo $?' '1\n2\n0\n' '' ''
@@ -130,8 +105,12 @@ testing 'local var +whiteout' \
130
105
testing 'escape passthrough' 'echo -e "a\nb\nc\td"' 'a\nb\nc\td\n' '' ''
131
106
132
107
testing 'trailing $ is literal' 'echo $' '$\n' '' ''
108
+ testing 'work after HERE' $'cat<<0;echo hello\npotato\n0' 'potato\nhello\n' '' ''
109
+ testing '<<""' $'cat<<"";echo hello\npotato\n\necho huh' 'potato\nhello\nhuh\n'\
110
+ '' ''
133
111
# TODO testing 'empty +() is literal' 'echo +()' '+()\n' '' ''
134
112
113
+ # shxpect "EOF" I$'<<EOF;echo hello'
135
114
shxpect 'queued work after HERE' I$'<<0;echo hello\n' E"> " I$'0\n' O$'hello\n'
136
115
shxpect '$_ preserved on assignment error' I$'true hello; a=1 b=2 c=${}\n' \
137
116
E E"$P" I$'echo $_\n' O$'hello\n'
@@ -471,6 +450,7 @@ testing 'sequence check' 'IFS=x; X=abxcd; echo ${X/bxc/g}' 'agd\n' '' ''
471
450
472
451
shxpect '${ with newline' I$'HELLO=abc; echo ${HELLO/b/\n' E"> " I$'}\n' O$'a c\n'
473
452
453
+ testing 'here0' 'cat<<<hello' 'hello\n' '' ''
474
454
shxpect 'here1' I$'POTATO=123; cat << EOF\n' E"> " \
475
455
I$'$POTATO\n' E"> " I$'EOF\n' O$'123\n'
476
456
shxpect 'here2' I$'POTATO=123; cat << E"O"F\n' E"> " \
@@ -739,3 +719,36 @@ testing '[[~]]' '[[ ~ == $HOME ]] && echo yes' 'yes\n' '' ''
739
719
#+ *) SKIPNEXT=1 ;;
740
720
#+ esac
741
721
722
+ # TODO: categorize tests
723
+
724
+ # TODO https://mywiki.wooledge.org/BashFAQ
725
+ # http://tiswww.case.edu/php/chet/bash/FAQ
726
+ # https://mywiki.wooledge.org/BashPitfalls#set_-euo_pipefail
727
+
728
+ # // ${#} ${#x} ${#@} ${#x[@]} ${#!} ${!#}
729
+ # // ${!} ${!@} ${!@Q} ${!x} ${!x@} ${!x@Q} ${!x#} ${!x[} ${!x[*]}
730
+
731
+ # Looked like a prefix but wasn't: three chars (@ # -) are both paremeter name
732
+ # and slice operator. When immediately followed by } it's parameter, otherwise
733
+ # we did NOT have a prefix and it's an operator.
734
+ #
735
+ # ${#-} ${#-abc}
736
+ # ${##} ${##0}
737
+ # ${#@} ${#@Q}
738
+ #
739
+ # backslash not discarded: echo "abc\"def"
740
+
741
+ # ${x:-y} use default
742
+ # ${x:=y} assign default (error if positional)
743
+ # ${x:?y} err if null
744
+ # ${x:+y} alt value
745
+ # ${x:off} ${x:off:len} off<0 from end (must ": -"), len<0 also from end must
746
+ # 0-based indexing
747
+ # ${@:off:len} positional parameters, off -1 = len, -len is error
748
+ # 1-based indexing
749
+
750
+ # [] wins over +()
751
+ # touch 'AB[DEF]'; echo AB[+(DEF]) AB[+(DEF)?
752
+ # AB[+(DEF]) AB[DEF]
753
+
754
+ # Testing shell corner cases _within_ a shell script is kind of hard.
0 commit comments