OILS / spec / builtins.test.sh View on Github | oilshell.org

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