1 #!/usr/bin/env bash
2
3 ### echo dashes
4 echo -
5 echo --
6 echo ---
7 # stdout-json: "-\n--\n---\n"
8
9 ### echo -en
10 echo -en 'abc\ndef\n'
11 # stdout-json: "abc\ndef\n"
12 # N-I dash stdout-json: "-en abc\ndef\n\n"
13
14 ### echo -ez (invalid flag)
15 # bash differs from the other two shells, but its behavior is possibly more
16 # sensible, if you're going to ignore the error. It doesn't make sense for the
17 # 'e' to mean 2 different things simultaneously: flag and literal to be
18 # printed.
19 echo -ez 'abc\n'
20 # stdout-json: "-ez abc\\n\n"
21 # BUG dash/mksh stdout-json: "-ez abc\n\n"
22
23 ### exec builtin
24 exec echo hi
25 # stdout: hi
26
27 ### exec builtin with redirects
28 exec 1>&2
29 echo 'to stderr'
30 # stdout-json: ""
31 # stderr: to stderr
32
33 ### exec builtin with here doc
34 # This has in a separate file because both code and data can be read from
35 # stdin.
36 $SH spec/exec-here-doc.sh
37 # stdout-json: "x=one\ny=two\nDONE\n"
38
39 ### cd and $PWD
40 cd /
41 echo $PWD
42 # stdout: /
43
44 ### $OLDPWD
45 cd /
46 cd $TMP
47 echo "old: $OLDPWD"
48 cd -
49 # stdout-json: "old: /\n/\n"
50
51 ### pushd/popd
52 set -o errexit
53 cd /
54 pushd $TMP
55 popd
56 pwd
57 # status: 0
58 # N-I dash/mksh status: 127
59
60 ### Source
61 lib=$TMP/spec-test-lib.sh
62 echo 'LIBVAR=libvar' > $lib
63 . $lib # dash doesn't have source
64 echo $LIBVAR
65 # stdout: libvar
66
67 ### Exit builtin
68 exit 3
69 # status: 3
70
71 ### Exit builtin with invalid arg
72 exit invalid
73 # Rationale: runtime errors are 1
74 # status: 1
75 # OK dash/bash status: 2
76
77 ### Exit builtin with too many args
78 exit 7 8 9
79 echo "no exit: $?"
80 # status: 0
81 # stdout-json: "no exit: 1\n"
82 # BUG dash status: 7
83 # BUG dash stdout-json: ""
84 # OK mksh status: 1
85 # OK mksh stdout-json: ""
86
87 ### time block
88 # bash and mksh work; dash does't.
89 # TODO: osh needs to implement BraceGroup redirect properly.
90 err=_tmp/time-$(basename $SH).txt
91 {
92 time {
93 sleep 0.01
94 sleep 0.02
95 }
96 } 2> $err
97 cat $err | grep --only-matching real
98 # Just check that we found 'real'.
99 # This is fiddly:
100 # | sed -n -E -e 's/.*(0m0\.03).*/\1/'
101 #
102 # status: 0
103 # stdout: real
104 # BUG dash status: 2
105 # BUG dash stdout-json: ""
106
107 ### time pipeline
108 time echo hi | wc -c
109 # stdout: 3
110 # status: 0
111
112 ### shift
113 set -- 1 2 3 4
114 shift
115 echo "$@"
116 shift 2
117 echo "$@"
118 # stdout-json: "2 3 4\n4\n"
119 # status: 0
120
121 ### Shifting too far
122 set -- 1
123 shift 2
124 # status: 1
125 # OK dash status: 2
126
127 ### Invalid shift argument
128 shift ZZZ
129 # status: 1
130 # OK dash status: 2
131 # BUG mksh status: 0
132
133 ### Read builtin
134 # NOTE: there are TABS below
135 read x <<EOF
136 A B C D E
137 FG
138 EOF
139 echo "[$x]"
140 # stdout: [A B C D E]
141 # status: 0
142
143 ### Read builtin with no newline.
144 # This is odd because the variable is populated successfully. OSH/Oil might
145 # need a separate put reading feature that doesn't use IFS.
146 echo -n ZZZ | { read x; echo $?; echo $x; }
147 # stdout-json: "1\nZZZ\n"
148 # status: 0
149
150 ### Read builtin with multiple variables
151 # NOTE: there are TABS below
152 read x y z <<EOF
153 A B C D E
154 FG
155 EOF
156 echo "$x/$y/$z"
157 # stdout: A/B/C D E
158 # status: 0
159
160 ### Read builtin with not enough variables
161 set -o errexit
162 set -o nounset # hm this doesn't change it
163 read x y z <<EOF
164 A B
165 EOF
166 echo /$x/$y/$z/
167 # stdout: /A/B//
168 # status: 0
169
170 ### get umask
171 umask | grep '[0-9]\+' # check for digits
172 # status: 0
173
174 ### set umask in octal
175 rm $TMP/umask-one $TMP/umask-two
176 umask 0002
177 echo one > $TMP/umask-one
178 umask 0022
179 echo two > $TMP/umask-two
180 stat -c '%a' $TMP/umask-one $TMP/umask-two
181 # status: 0
182 # stdout-json: "664\n644\n"
183 # stderr-json: ""
184
185 ### set umask symbolically
186 rm $TMP/umask-one $TMP/umask-two
187 echo one > $TMP/umask-one
188 umask g-w,o-w
189 echo two > $TMP/umask-two
190 stat -c '%a' $TMP/umask-one $TMP/umask-two
191 # status: 0
192 # stdout-json: "664\n644\n"
193 # stderr-json: ""
194