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