1 |
|
2 |
#### exec builtin |
3 |
exec echo hi |
4 |
## stdout: hi |
5 |
|
6 |
#### exec builtin with redirects |
7 |
exec 1>&2 |
8 |
echo 'to stderr' |
9 |
## stdout-json: "" |
10 |
## stderr: to stderr |
11 |
|
12 |
#### exec builtin with here doc |
13 |
# This has in a separate file because both code and data can be read from |
14 |
# stdin. |
15 |
$SH $REPO_ROOT/spec/bin/builtins-exec-here-doc-helper.sh |
16 |
## STDOUT: |
17 |
x=one |
18 |
y=two |
19 |
DONE |
20 |
## END |
21 |
|
22 |
#### exec builtin accepts -- |
23 |
exec -- echo hi |
24 |
## STDOUT: |
25 |
hi |
26 |
## END |
27 |
## BUG dash status: 127 |
28 |
## BUG dash stdout-json: "" |
29 |
|
30 |
#### exec -- 2>&1 |
31 |
exec -- 3>&1 |
32 |
echo stdout 1>&3 |
33 |
## STDOUT: |
34 |
stdout |
35 |
## END |
36 |
## BUG dash status: 127 |
37 |
## BUG dash stdout-json: "" |
38 |
## BUG mksh status: -11 |
39 |
## BUG mksh stdout-json: "" |
40 |
|
41 |
#### cd and $PWD |
42 |
cd / |
43 |
echo $PWD |
44 |
## stdout: / |
45 |
|
46 |
#### cd BAD/.. |
47 |
|
48 |
# Odd divergence in shells: dash and mksh normalize the path and don't check |
49 |
# this error. |
50 |
# TODO: I would like OSH to behave like bash and zsh, but it separting chdir_arg and |
51 |
# pwd_arg breaks case 17. |
52 |
|
53 |
cd nonexistent_ZZ/.. |
54 |
echo status=$? |
55 |
## STDOUT: |
56 |
status=1 |
57 |
## END |
58 |
## BUG dash/mksh STDOUT: |
59 |
status=0 |
60 |
## END |
61 |
|
62 |
#### $OLDPWD |
63 |
cd / |
64 |
cd $TMP |
65 |
echo "old: $OLDPWD" |
66 |
env | grep OLDPWD # It's EXPORTED too! |
67 |
cd - |
68 |
## STDOUT: |
69 |
old: / |
70 |
OLDPWD=/ |
71 |
/ |
72 |
## END |
73 |
## BUG mksh STDOUT: |
74 |
old: / |
75 |
/ |
76 |
## END |
77 |
## BUG zsh STDOUT: |
78 |
old: / |
79 |
OLDPWD=/ |
80 |
## END |
81 |
|
82 |
#### pwd |
83 |
cd / |
84 |
pwd |
85 |
## STDOUT: |
86 |
/ |
87 |
## END |
88 |
|
89 |
#### pwd after cd .. |
90 |
dir=$TMP/dir-one/dir-two |
91 |
mkdir -p $dir |
92 |
cd $dir |
93 |
echo $(basename $(pwd)) |
94 |
cd .. |
95 |
echo $(basename $(pwd)) |
96 |
## STDOUT: |
97 |
dir-two |
98 |
dir-one |
99 |
## END |
100 |
|
101 |
#### pwd with symlink and -P |
102 |
tmp=$TMP/builtins-pwd-1 |
103 |
mkdir -p $tmp/target |
104 |
ln -s -f $tmp/target $tmp/symlink |
105 |
|
106 |
cd $tmp/symlink |
107 |
|
108 |
echo pwd: |
109 |
basename $(pwd) |
110 |
|
111 |
echo pwd -P: |
112 |
basename $(pwd -P) |
113 |
|
114 |
## STDOUT: |
115 |
pwd: |
116 |
symlink |
117 |
pwd -P: |
118 |
target |
119 |
## END |
120 |
|
121 |
#### setting $PWD doesn't affect the value of 'pwd' builtin |
122 |
dir=/tmp/oil-spec-test/pwd |
123 |
mkdir -p $dir |
124 |
cd $dir |
125 |
|
126 |
PWD=foo |
127 |
echo before $PWD |
128 |
pwd |
129 |
echo after $PWD |
130 |
## STDOUT: |
131 |
before foo |
132 |
/tmp/oil-spec-test/pwd |
133 |
after foo |
134 |
## END |
135 |
|
136 |
#### unset PWD; then pwd |
137 |
dir=/tmp/oil-spec-test/pwd |
138 |
mkdir -p $dir |
139 |
cd $dir |
140 |
|
141 |
unset PWD |
142 |
echo PWD=$PWD |
143 |
pwd |
144 |
echo PWD=$PWD |
145 |
## STDOUT: |
146 |
PWD= |
147 |
/tmp/oil-spec-test/pwd |
148 |
PWD= |
149 |
## END |
150 |
|
151 |
#### 'unset PWD; pwd' before any cd (tickles a rare corner case) |
152 |
dir=/tmp/oil-spec-test/pwd-2 |
153 |
mkdir -p $dir |
154 |
cd $dir |
155 |
|
156 |
# ensure clean shell process state |
157 |
$SH -c 'unset PWD; pwd' |
158 |
|
159 |
## STDOUT: |
160 |
/tmp/oil-spec-test/pwd-2 |
161 |
## END |
162 |
|
163 |
#### lie about PWD; pwd before any cd |
164 |
dir=/tmp/oil-spec-test/pwd-3 |
165 |
mkdir -p $dir |
166 |
cd $dir |
167 |
|
168 |
# ensure clean shell process state |
169 |
$SH -c 'PWD=foo; pwd' |
170 |
|
171 |
## STDOUT: |
172 |
/tmp/oil-spec-test/pwd-3 |
173 |
## END |
174 |
|
175 |
#### remove pwd dir |
176 |
dir=/tmp/oil-spec-test/pwd |
177 |
mkdir -p $dir |
178 |
cd $dir |
179 |
pwd |
180 |
rmdir $dir |
181 |
echo status=$? |
182 |
pwd |
183 |
echo status=$? |
184 |
## STDOUT: |
185 |
/tmp/oil-spec-test/pwd |
186 |
status=0 |
187 |
/tmp/oil-spec-test/pwd |
188 |
status=0 |
189 |
## END |
190 |
## OK mksh STDOUT: |
191 |
/tmp/oil-spec-test/pwd |
192 |
status=0 |
193 |
status=1 |
194 |
## END |
195 |
|
196 |
#### pwd in symlinked dir on shell initialization |
197 |
tmp=$TMP/builtins-pwd-2 |
198 |
mkdir -p $tmp |
199 |
mkdir -p $tmp/target |
200 |
ln -s -f $tmp/target $tmp/symlink |
201 |
|
202 |
cd $tmp/symlink |
203 |
$SH -c 'basename $(pwd)' |
204 |
unset PWD |
205 |
$SH -c 'basename $(pwd)' |
206 |
|
207 |
## STDOUT: |
208 |
symlink |
209 |
target |
210 |
## END |
211 |
## OK mksh STDOUT: |
212 |
target |
213 |
target |
214 |
## END |
215 |
## stderr-json: "" |
216 |
|
217 |
#### Test the current directory after 'cd ..' involving symlinks |
218 |
dir=$TMP/symlinktest |
219 |
mkdir -p $dir |
220 |
cd $dir |
221 |
mkdir -p a/b/c |
222 |
mkdir -p a/b/d |
223 |
ln -s -f a/b/c c > /dev/null |
224 |
cd c |
225 |
cd .. |
226 |
# Expecting a c/ (since we are in symlinktest) but osh gives c d (thinks we are |
227 |
# in b/) |
228 |
ls |
229 |
## STDOUT: |
230 |
a |
231 |
c |
232 |
## END |
233 |
|
234 |
#### cd with no arguments |
235 |
HOME=$TMP/home |
236 |
mkdir -p $HOME |
237 |
cd |
238 |
test $(pwd) = "$HOME" && echo OK |
239 |
## stdout: OK |
240 |
|
241 |
#### cd to nonexistent dir |
242 |
cd /nonexistent/dir |
243 |
echo status=$? |
244 |
## stdout: status=1 |
245 |
## OK dash/mksh stdout: status=2 |
246 |
|
247 |
#### cd away from dir that was deleted |
248 |
dir=$TMP/cd-nonexistent |
249 |
mkdir -p $dir |
250 |
cd $dir |
251 |
rmdir $dir |
252 |
cd $TMP |
253 |
echo $(basename $OLDPWD) |
254 |
echo status=$? |
255 |
## STDOUT: |
256 |
cd-nonexistent |
257 |
status=0 |
258 |
## END |
259 |
|
260 |
#### cd permits double bare dash |
261 |
cd -- / |
262 |
echo $PWD |
263 |
## stdout: / |
264 |
|
265 |
#### cd to symlink with -L and -P |
266 |
targ=$TMP/cd-symtarget |
267 |
lnk=$TMP/cd-symlink |
268 |
mkdir -p $targ |
269 |
ln -s $targ $lnk |
270 |
|
271 |
# -L behavior is the default |
272 |
cd $lnk |
273 |
test $PWD = "$TMP/cd-symlink" && echo OK |
274 |
|
275 |
cd -L $lnk |
276 |
test $PWD = "$TMP/cd-symlink" && echo OK |
277 |
|
278 |
cd -P $lnk |
279 |
test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD |
280 |
## STDOUT: |
281 |
OK |
282 |
OK |
283 |
OK |
284 |
## END |
285 |
|
286 |
#### cd to relative path with -L and -P |
287 |
die() { echo "$@"; exit 1; } |
288 |
|
289 |
targ=$TMP/cd-symtarget/subdir |
290 |
lnk=$TMP/cd-symlink |
291 |
mkdir -p $targ |
292 |
ln -s $TMP/cd-symtarget $lnk |
293 |
|
294 |
# -L behavior is the default |
295 |
cd $lnk/subdir |
296 |
test $PWD = "$TMP/cd-symlink/subdir" || die "failed" |
297 |
cd .. |
298 |
test $PWD = "$TMP/cd-symlink" && echo OK |
299 |
|
300 |
cd $lnk/subdir |
301 |
test $PWD = "$TMP/cd-symlink/subdir" || die "failed" |
302 |
cd -L .. |
303 |
test $PWD = "$TMP/cd-symlink" && echo OK |
304 |
|
305 |
cd $lnk/subdir |
306 |
test $PWD = "$TMP/cd-symlink/subdir" || die "failed" |
307 |
cd -P .. |
308 |
test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD |
309 |
## STDOUT: |
310 |
OK |
311 |
OK |
312 |
OK |
313 |
## END |
314 |
|
315 |
#### Exit out of function |
316 |
f() { exit 3; } |
317 |
f |
318 |
exit 4 |
319 |
## status: 3 |
320 |
|
321 |
#### Exit builtin with invalid arg |
322 |
exit invalid |
323 |
# Rationale: runtime errors are 1 |
324 |
## status: 1 |
325 |
## OK dash/bash status: 2 |
326 |
## BUG zsh status: 0 |
327 |
|
328 |
#### Exit builtin with too many args |
329 |
# This is a parse error in OSH. |
330 |
exit 7 8 9 |
331 |
echo status=$? |
332 |
## status: 2 |
333 |
## stdout-json: "" |
334 |
## BUG bash/zsh status: 0 |
335 |
## BUG bash/zsh stdout: status=1 |
336 |
## BUG dash status: 7 |
337 |
## BUG dash stdout-json: "" |
338 |
## OK mksh status: 1 |
339 |
## OK mksh stdout-json: "" |
340 |
|
341 |
#### time with brace group argument |
342 |
|
343 |
err=_tmp/time-$(basename $SH).txt |
344 |
{ |
345 |
time { |
346 |
sleep 0.01 |
347 |
sleep 0.02 |
348 |
} |
349 |
} 2> $err |
350 |
|
351 |
grep --only-matching user $err |
352 |
echo result=$? |
353 |
|
354 |
# Regression: check fractional seconds |
355 |
gawk ' |
356 |
BEGIN { ok = 0 } |
357 |
match( $0, /\.([0-9]+)/, m) { |
358 |
if (m[1] > 0) { # check fractional seconds |
359 |
ok = 1 |
360 |
} |
361 |
} |
362 |
END { if (ok) { print "non-zero" } } |
363 |
' $err |
364 |
|
365 |
## status: 0 |
366 |
## STDOUT: |
367 |
user |
368 |
result=0 |
369 |
non-zero |
370 |
## END |
371 |
|
372 |
# time doesn't accept a block? |
373 |
## BUG zsh STDOUT: |
374 |
result=1 |
375 |
## END |
376 |
|
377 |
# dash doesn't have time keyword |
378 |
## N-I dash status: 2 |
379 |
## N-I dash stdout-json: "" |
380 |
|
381 |
#### time pipeline |
382 |
time echo hi | wc -c |
383 |
## stdout: 3 |
384 |
## status: 0 |
385 |
|
386 |
#### shift |
387 |
set -- 1 2 3 4 |
388 |
shift |
389 |
echo "$@" |
390 |
shift 2 |
391 |
echo "$@" |
392 |
## stdout-json: "2 3 4\n4\n" |
393 |
## status: 0 |
394 |
|
395 |
#### Shifting too far |
396 |
set -- 1 |
397 |
shift 2 |
398 |
## status: 1 |
399 |
## OK dash status: 2 |
400 |
|
401 |
#### Invalid shift argument |
402 |
shift ZZZ |
403 |
## status: 2 |
404 |
## OK bash status: 1 |
405 |
## BUG mksh/zsh status: 0 |
406 |
|
407 |
#### get umask |
408 |
umask | grep '[0-9]\+' # check for digits |
409 |
## status: 0 |
410 |
|
411 |
#### set umask in octal |
412 |
rm -f $TMP/umask-one $TMP/umask-two |
413 |
umask 0002 |
414 |
echo one > $TMP/umask-one |
415 |
umask 0022 |
416 |
echo two > $TMP/umask-two |
417 |
stat -c '%a' $TMP/umask-one $TMP/umask-two |
418 |
## status: 0 |
419 |
## stdout-json: "664\n644\n" |
420 |
## stderr-json: "" |
421 |
|
422 |
#### set umask symbolically |
423 |
umask 0002 # begin in a known state for the test |
424 |
rm -f $TMP/umask-one $TMP/umask-two |
425 |
echo one > $TMP/umask-one |
426 |
umask g-w,o-w |
427 |
echo two > $TMP/umask-two |
428 |
stat -c '%a' $TMP/umask-one $TMP/umask-two |
429 |
## status: 0 |
430 |
## STDOUT: |
431 |
664 |
432 |
644 |
433 |
## END |
434 |
## stderr-json: "" |