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 |
env | grep OLDPWD # It's EXPORTED too! |
29 |
cd - |
30 |
## STDOUT: |
31 |
old: / |
32 |
OLDPWD=/ |
33 |
/ |
34 |
## END |
35 |
## BUG mksh STDOUT: |
36 |
old: / |
37 |
/ |
38 |
## END |
39 |
## BUG zsh STDOUT: |
40 |
old: / |
41 |
OLDPWD=/ |
42 |
## END |
43 |
|
44 |
#### pwd |
45 |
cd / |
46 |
pwd |
47 |
## STDOUT: |
48 |
/ |
49 |
## END |
50 |
|
51 |
#### pwd after cd .. |
52 |
dir=$TMP/dir-one/dir-two |
53 |
mkdir -p $dir |
54 |
cd $dir |
55 |
echo $(basename $(pwd)) |
56 |
cd .. |
57 |
echo $(basename $(pwd)) |
58 |
## STDOUT: |
59 |
dir-two |
60 |
dir-one |
61 |
## END |
62 |
|
63 |
#### pwd with symlink and -P |
64 |
tmp=$TMP/builtins-pwd-1 |
65 |
mkdir -p $tmp/target |
66 |
ln -s -f $tmp/target $tmp/symlink |
67 |
|
68 |
cd $tmp/symlink |
69 |
|
70 |
echo pwd: |
71 |
basename $(pwd) |
72 |
|
73 |
echo pwd -P: |
74 |
basename $(pwd -P) |
75 |
|
76 |
## STDOUT: |
77 |
pwd: |
78 |
symlink |
79 |
pwd -P: |
80 |
target |
81 |
## END |
82 |
|
83 |
#### setting $PWD doesn't affect the value of 'pwd' builtin |
84 |
dir=/tmp/oil-spec-test/pwd |
85 |
mkdir -p $dir |
86 |
cd $dir |
87 |
|
88 |
PWD=foo |
89 |
echo before $PWD |
90 |
pwd |
91 |
echo after $PWD |
92 |
## STDOUT: |
93 |
before foo |
94 |
/tmp/oil-spec-test/pwd |
95 |
after foo |
96 |
## END |
97 |
|
98 |
#### unset PWD; then pwd |
99 |
dir=/tmp/oil-spec-test/pwd |
100 |
mkdir -p $dir |
101 |
cd $dir |
102 |
|
103 |
unset PWD |
104 |
echo PWD=$PWD |
105 |
pwd |
106 |
echo PWD=$PWD |
107 |
## STDOUT: |
108 |
PWD= |
109 |
/tmp/oil-spec-test/pwd |
110 |
PWD= |
111 |
## END |
112 |
|
113 |
#### 'unset PWD; pwd' before any cd (tickles a rare corner case) |
114 |
dir=/tmp/oil-spec-test/pwd-2 |
115 |
mkdir -p $dir |
116 |
cd $dir |
117 |
|
118 |
# ensure clean shell process state |
119 |
$SH -c 'unset PWD; pwd' |
120 |
|
121 |
## STDOUT: |
122 |
/tmp/oil-spec-test/pwd-2 |
123 |
## END |
124 |
|
125 |
#### lie about PWD; pwd before any cd |
126 |
dir=/tmp/oil-spec-test/pwd-3 |
127 |
mkdir -p $dir |
128 |
cd $dir |
129 |
|
130 |
# ensure clean shell process state |
131 |
$SH -c 'PWD=foo; pwd' |
132 |
|
133 |
## STDOUT: |
134 |
/tmp/oil-spec-test/pwd-3 |
135 |
## END |
136 |
|
137 |
#### remove pwd dir |
138 |
dir=/tmp/oil-spec-test/pwd |
139 |
mkdir -p $dir |
140 |
cd $dir |
141 |
pwd |
142 |
rmdir $dir |
143 |
echo status=$? |
144 |
pwd |
145 |
echo status=$? |
146 |
## STDOUT: |
147 |
/tmp/oil-spec-test/pwd |
148 |
status=0 |
149 |
/tmp/oil-spec-test/pwd |
150 |
status=0 |
151 |
## END |
152 |
## OK mksh STDOUT: |
153 |
/tmp/oil-spec-test/pwd |
154 |
status=0 |
155 |
status=1 |
156 |
## END |
157 |
|
158 |
#### pwd in symlinked dir on shell initialization |
159 |
tmp=$TMP/builtins-pwd-2 |
160 |
mkdir -p $tmp |
161 |
mkdir -p $tmp/target |
162 |
ln -s -f $tmp/target $tmp/symlink |
163 |
|
164 |
cd $tmp/symlink |
165 |
$SH -c 'basename $(pwd)' |
166 |
unset PWD |
167 |
$SH -c 'basename $(pwd)' |
168 |
|
169 |
## STDOUT: |
170 |
symlink |
171 |
target |
172 |
## END |
173 |
## OK mksh STDOUT: |
174 |
target |
175 |
target |
176 |
## END |
177 |
## stderr-json: "" |
178 |
|
179 |
#### Test the current directory after 'cd ..' involving symlinks |
180 |
dir=$TMP/symlinktest |
181 |
mkdir -p $dir |
182 |
cd $dir |
183 |
mkdir -p a/b/c |
184 |
mkdir -p a/b/d |
185 |
ln -s -f a/b/c c > /dev/null |
186 |
cd c |
187 |
cd .. |
188 |
# Expecting a c/ (since we are in symlinktest) but osh gives c d (thinks we are |
189 |
# in b/) |
190 |
ls |
191 |
## STDOUT: |
192 |
a |
193 |
c |
194 |
## END |
195 |
|
196 |
#### cd with no arguments |
197 |
HOME=$TMP/home |
198 |
mkdir -p $HOME |
199 |
cd |
200 |
test $(pwd) = "$HOME" && echo OK |
201 |
## stdout: OK |
202 |
|
203 |
#### cd to nonexistent dir |
204 |
cd /nonexistent/dir |
205 |
echo status=$? |
206 |
## stdout: status=1 |
207 |
## OK dash/mksh stdout: status=2 |
208 |
|
209 |
#### cd away from dir that was deleted |
210 |
dir=$TMP/cd-nonexistent |
211 |
mkdir -p $dir |
212 |
cd $dir |
213 |
rmdir $dir |
214 |
cd $TMP |
215 |
echo $(basename $OLDPWD) |
216 |
echo status=$? |
217 |
## STDOUT: |
218 |
cd-nonexistent |
219 |
status=0 |
220 |
## END |
221 |
|
222 |
#### cd permits double bare dash |
223 |
cd -- / |
224 |
echo $PWD |
225 |
## stdout: / |
226 |
|
227 |
#### cd to symlink with -L and -P |
228 |
targ=$TMP/cd-symtarget |
229 |
lnk=$TMP/cd-symlink |
230 |
mkdir -p $targ |
231 |
ln -s $targ $lnk |
232 |
|
233 |
# -L behavior is the default |
234 |
cd $lnk |
235 |
test $PWD = "$TMP/cd-symlink" && echo OK |
236 |
|
237 |
cd -L $lnk |
238 |
test $PWD = "$TMP/cd-symlink" && echo OK |
239 |
|
240 |
cd -P $lnk |
241 |
test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD |
242 |
## STDOUT: |
243 |
OK |
244 |
OK |
245 |
OK |
246 |
## END |
247 |
|
248 |
#### cd to relative path with -L and -P |
249 |
die() { echo "$@"; exit 1; } |
250 |
|
251 |
targ=$TMP/cd-symtarget/subdir |
252 |
lnk=$TMP/cd-symlink |
253 |
mkdir -p $targ |
254 |
ln -s $targ $lnk |
255 |
|
256 |
# -L behavior is the default |
257 |
cd $lnk/subdir |
258 |
test $PWD = "$TMP/cd-symlink/subdir" || die "failed" |
259 |
cd .. |
260 |
test $PWD = "$TMP/cd-symlink" && echo OK |
261 |
|
262 |
cd $lnk/subdir |
263 |
test $PWD = "$TMP/cd-symlink/subdir" || die "failed" |
264 |
cd -L .. |
265 |
test $PWD = "$TMP/cd-symlink" && echo OK |
266 |
|
267 |
cd $lnk/subdir |
268 |
test $PWD = "$TMP/cd-symlink/subdir" || die "failed" |
269 |
cd -P .. |
270 |
test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD |
271 |
## STDOUT: |
272 |
OK |
273 |
OK |
274 |
OK |
275 |
## END |
276 |
|
277 |
#### Exit out of function |
278 |
f() { exit 3; } |
279 |
f |
280 |
exit 4 |
281 |
## status: 3 |
282 |
|
283 |
#### Exit builtin with invalid arg |
284 |
exit invalid |
285 |
# Rationale: runtime errors are 1 |
286 |
## status: 1 |
287 |
## OK dash/bash status: 2 |
288 |
## BUG zsh status: 0 |
289 |
|
290 |
#### Exit builtin with too many args |
291 |
# This is a parse error in OSH. |
292 |
exit 7 8 9 |
293 |
echo status=$? |
294 |
## status: 2 |
295 |
## stdout-json: "" |
296 |
## BUG bash/zsh status: 0 |
297 |
## BUG bash/zsh stdout: status=1 |
298 |
## BUG dash status: 7 |
299 |
## BUG dash stdout-json: "" |
300 |
## OK mksh status: 1 |
301 |
## OK mksh stdout-json: "" |
302 |
|
303 |
#### time block |
304 |
# bash and mksh work; dash does't. |
305 |
# TODO: osh needs to implement BraceGroup redirect properly. |
306 |
err=_tmp/time-$(basename $SH).txt |
307 |
{ |
308 |
time { |
309 |
sleep 0.01 |
310 |
sleep 0.02 |
311 |
} |
312 |
} 2> $err |
313 |
cat $err | grep --only-matching user |
314 |
# Just check that we found 'user'. |
315 |
# This is fiddly: |
316 |
# | sed -n -E -e 's/.*(0m0\.03).*/\1/' |
317 |
# |
318 |
## status: 0 |
319 |
## stdout: user |
320 |
|
321 |
# not parsed |
322 |
## BUG dash status: 2 |
323 |
## BUG dash stdout-json: "" |
324 |
|
325 |
# time is a builtin in zsh? |
326 |
## BUG zsh status: 1 |
327 |
## BUG zsh stdout-json: "" |
328 |
|
329 |
#### time pipeline |
330 |
time echo hi | wc -c |
331 |
## stdout: 3 |
332 |
## status: 0 |
333 |
|
334 |
#### shift |
335 |
set -- 1 2 3 4 |
336 |
shift |
337 |
echo "$@" |
338 |
shift 2 |
339 |
echo "$@" |
340 |
## stdout-json: "2 3 4\n4\n" |
341 |
## status: 0 |
342 |
|
343 |
#### Shifting too far |
344 |
set -- 1 |
345 |
shift 2 |
346 |
## status: 1 |
347 |
## OK dash status: 2 |
348 |
|
349 |
#### Invalid shift argument |
350 |
shift ZZZ |
351 |
## status: 2 |
352 |
## OK bash status: 1 |
353 |
## BUG mksh/zsh status: 0 |
354 |
|
355 |
#### get umask |
356 |
umask | grep '[0-9]\+' # check for digits |
357 |
## status: 0 |
358 |
|
359 |
#### set umask in octal |
360 |
rm -f $TMP/umask-one $TMP/umask-two |
361 |
umask 0002 |
362 |
echo one > $TMP/umask-one |
363 |
umask 0022 |
364 |
echo two > $TMP/umask-two |
365 |
stat -c '%a' $TMP/umask-one $TMP/umask-two |
366 |
## status: 0 |
367 |
## stdout-json: "664\n644\n" |
368 |
## stderr-json: "" |
369 |
|
370 |
#### set umask symbolically |
371 |
umask 0002 # begin in a known state for the test |
372 |
rm $TMP/umask-one $TMP/umask-two |
373 |
echo one > $TMP/umask-one |
374 |
umask g-w,o-w |
375 |
echo two > $TMP/umask-two |
376 |
stat -c '%a' $TMP/umask-one $TMP/umask-two |
377 |
## status: 0 |
378 |
## STDOUT: |
379 |
664 |
380 |
644 |
381 |
## END |
382 |
## stderr-json: "" |