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