1 #!/usr/bin/env bash
2
3 #### exec builtin
4 exec echo hi
5 ## stdout: hi
6
7 #### exec builtin with redirects
8 exec 1>&2
9 echo 'to stderr'
10 ## stdout-json: ""
11 ## stderr: to stderr
12
13 #### exec builtin with here doc
14 # This has in a separate file because both code and data can be read from
15 # stdin.
16 $SH spec/builtins-exec-here-doc-helper.sh
17 ## stdout-json: "x=one\ny=two\nDONE\n"
18
19 #### cd and $PWD
20 cd /
21 echo $PWD
22 ## stdout: /
23
24 #### $OLDPWD
25 cd /
26 cd $TMP
27 echo "old: $OLDPWD"
28 cd -
29 ## stdout-json: "old: /\n/\n"
30
31 #### pwd
32 cd /
33 pwd
34 ## STDOUT:
35 /
36 ## END
37
38 #### pwd after cd ..
39 dir=$TMP/dir-one/dir-two
40 mkdir -p $dir
41 cd $dir
42 echo $(basename $(pwd))
43 cd ..
44 echo $(basename $(pwd))
45 ## STDOUT:
46 dir-two
47 dir-one
48 ## END
49
50 #### pwd -P
51 tmp=$TMP/builtins-pwd-1
52 mkdir -p $tmp
53 mkdir -p $tmp/symtarg
54 ln -s $tmp/symtarg $tmp/symlink
55 cd $tmp/symlink
56 basename $(pwd -P)
57 cd $tmp
58 rmdir $tmp/symtarg
59 rm $tmp/symlink
60 ## stdout: symtarg
61
62 #### Test the current directory after 'cd ..' involving symlinks
63 dir=$TMP/symlinktest
64 mkdir -p $dir
65 cd $dir
66 mkdir -p a/b/c
67 mkdir -p a/b/d
68 ln -s -f a/b/c c > /dev/null
69 cd c
70 cd ..
71 # Expecting a c/ (since we are in symlinktest) but osh gives c d (thinks we are
72 # in b/)
73 ls
74 ## STDOUT:
75 a
76 c
77 ## END
78
79 #### cd with no arguments
80 HOME=$TMP/home
81 mkdir -p $HOME
82 cd
83 test $(pwd) = "$HOME" && echo OK
84 ## stdout: OK
85
86 #### cd to nonexistent dir
87 cd /nonexistent/dir
88 echo status=$?
89 ## stdout: status=1
90 ## OK dash/mksh stdout: status=2
91
92 #### cd away from dir that was deleted
93 dir=$TMP/cd-nonexistent
94 mkdir -p $dir
95 cd $dir
96 rmdir $dir
97 cd $TMP
98 echo $(basename $OLDPWD)
99 echo status=$?
100 ## STDOUT:
101 cd-nonexistent
102 status=0
103 ## END
104
105 #### cd permits double bare dash
106 cd -- /
107 echo $PWD
108 ## stdout: /
109
110 #### cd to symlink with -L and -P
111 targ=$TMP/cd-symtarget
112 lnk=$TMP/cd-symlink
113 mkdir -p $targ
114 ln -s $targ $lnk
115
116 # -L behavior is the default
117 cd $lnk
118 test $PWD = "$TMP/cd-symlink" && echo OK
119
120 cd -L $lnk
121 test $PWD = "$TMP/cd-symlink" && echo OK
122
123 cd -P $lnk
124 test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD
125 ## STDOUT:
126 OK
127 OK
128 OK
129 ## END
130
131 #### cd to relative path with -L and -P
132 die() { echo "$@"; exit 1; }
133
134 targ=$TMP/cd-symtarget/subdir
135 lnk=$TMP/cd-symlink
136 mkdir -p $targ
137 ln -s $targ $lnk
138
139 # -L behavior is the default
140 cd $lnk/subdir
141 test $PWD = "$TMP/cd-symlink/subdir" || die "failed"
142 cd ..
143 test $PWD = "$TMP/cd-symlink" && echo OK
144
145 cd $lnk/subdir
146 test $PWD = "$TMP/cd-symlink/subdir" || die "failed"
147 cd -L ..
148 test $PWD = "$TMP/cd-symlink" && echo OK
149
150 cd $lnk/subdir
151 test $PWD = "$TMP/cd-symlink/subdir" || die "failed"
152 cd -P ..
153 test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD
154 ## STDOUT:
155 OK
156 OK
157 OK
158 ## END
159
160 #### pushd/popd
161 set -o errexit
162 cd /
163 pushd $TMP
164 popd
165 pwd
166 ## status: 0
167 ## N-I dash/mksh status: 127
168
169 #### Exit out of function
170 f() { exit 3; }
171 f
172 exit 4
173 ## status: 3
174
175 #### Exit builtin with invalid arg
176 exit invalid
177 # Rationale: runtime errors are 1
178 ## status: 1
179 ## OK dash/bash status: 2
180
181 #### Exit builtin with too many args
182 # This is a parse error in OSH.
183 exit 7 8 9
184 echo status=$?
185 ## status: 2
186 ## stdout-json: ""
187 ## BUG bash status: 0
188 ## BUG bash stdout: status=1
189 ## BUG dash status: 7
190 ## BUG dash stdout-json: ""
191 ## OK mksh status: 1
192 ## OK mksh stdout-json: ""
193
194 #### time block
195 # bash and mksh work; dash does't.
196 # TODO: osh needs to implement BraceGroup redirect properly.
197 err=_tmp/time-$(basename $SH).txt
198 {
199 time {
200 sleep 0.01
201 sleep 0.02
202 }
203 } 2> $err
204 cat $err | grep --only-matching real
205 # Just check that we found 'real'.
206 # This is fiddly:
207 # | sed -n -E -e 's/.*(0m0\.03).*/\1/'
208 #
209 ## status: 0
210 ## stdout: real
211 ## BUG dash status: 2
212 ## BUG dash stdout-json: ""
213
214 #### time pipeline
215 time echo hi | wc -c
216 ## stdout: 3
217 ## status: 0
218
219 #### shift
220 set -- 1 2 3 4
221 shift
222 echo "$@"
223 shift 2
224 echo "$@"
225 ## stdout-json: "2 3 4\n4\n"
226 ## status: 0
227
228 #### Shifting too far
229 set -- 1
230 shift 2
231 ## status: 1
232 ## OK dash status: 2
233
234 #### Invalid shift argument
235 shift ZZZ
236 ## status: 1
237 ## OK dash status: 2
238 ## BUG mksh status: 0
239
240 #### get umask
241 umask | grep '[0-9]\+' # check for digits
242 ## status: 0
243
244 #### set umask in octal
245 rm -f $TMP/umask-one $TMP/umask-two
246 umask 0002
247 echo one > $TMP/umask-one
248 umask 0022
249 echo two > $TMP/umask-two
250 stat -c '%a' $TMP/umask-one $TMP/umask-two
251 ## status: 0
252 ## stdout-json: "664\n644\n"
253 ## stderr-json: ""
254
255 #### set umask symbolically
256 umask 0002 # begin in a known state for the test
257 rm $TMP/umask-one $TMP/umask-two
258 echo one > $TMP/umask-one
259 umask g-w,o-w
260 echo two > $TMP/umask-two
261 stat -c '%a' $TMP/umask-one $TMP/umask-two
262 ## status: 0
263 ## STDOUT:
264 664
265 644
266 ## END
267 ## stderr-json: ""