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 ### cd with no arguments
32 HOME=$TMP/home
33 mkdir -p $HOME
34 cd
35 test $(pwd) = "$HOME" && echo OK
36 # stdout: OK
37
38 ### cd to nonexistent dir
39 cd /nonexistent/dir
40 echo status=$?
41 # stdout: status=1
42 # OK dash/mksh stdout: status=2
43
44 ### cd away from dir that was deleted
45 dir=$TMP/cd-nonexistent
46 mkdir -p $dir
47 cd $dir
48 rmdir $dir
49 cd $TMP
50 echo $(basename $OLDPWD)
51 echo status=$?
52 ## STDOUT:
53 cd-nonexistent
54 status=0
55 ## END
56
57 ### pushd/popd
58 set -o errexit
59 cd /
60 pushd $TMP
61 popd
62 pwd
63 # status: 0
64 # N-I dash/mksh status: 127
65
66 ### Eval
67 eval "a=3"
68 echo $a
69 # stdout: 3
70
71 ### Source
72 lib=$TMP/spec-test-lib.sh
73 echo 'LIBVAR=libvar' > $lib
74 . $lib # dash doesn't have source
75 echo $LIBVAR
76 # stdout: libvar
77
78 ### Source nonexistent
79 source /nonexistent/path
80 echo status=$?
81 # stdout: status=1
82 # OK dash stdout: status=127
83
84 ### Source with no arguments
85 source
86 echo status=$?
87 # stdout: status=1
88 # OK bash stdout: status=2
89 # OK dash stdout: status=127
90
91 ### Exit builtin
92 f() { exit 3; }
93 f
94 exit 4
95 # status: 3
96
97 ### Exit builtin with invalid arg
98 exit invalid
99 # Rationale: runtime errors are 1
100 # status: 1
101 # OK dash/bash status: 2
102
103 ### Exit builtin with too many args
104 # This is a parse error in OSH.
105 exit 7 8 9
106 echo status=$?
107 # status: 2
108 # stdout-json: ""
109 # BUG bash status: 0
110 # BUG bash stdout: status=1
111 # BUG dash status: 7
112 # BUG dash stdout-json: ""
113 # OK mksh status: 1
114 # OK mksh stdout-json: ""
115
116 ### time block
117 # bash and mksh work; dash does't.
118 # TODO: osh needs to implement BraceGroup redirect properly.
119 err=_tmp/time-$(basename $SH).txt
120 {
121 time {
122 sleep 0.01
123 sleep 0.02
124 }
125 } 2> $err
126 cat $err | grep --only-matching real
127 # Just check that we found 'real'.
128 # This is fiddly:
129 # | sed -n -E -e 's/.*(0m0\.03).*/\1/'
130 #
131 # status: 0
132 # stdout: real
133 # BUG dash status: 2
134 # BUG dash stdout-json: ""
135
136 ### time pipeline
137 time echo hi | wc -c
138 # stdout: 3
139 # status: 0
140
141 ### shift
142 set -- 1 2 3 4
143 shift
144 echo "$@"
145 shift 2
146 echo "$@"
147 # stdout-json: "2 3 4\n4\n"
148 # status: 0
149
150 ### Shifting too far
151 set -- 1
152 shift 2
153 # status: 1
154 # OK dash status: 2
155
156 ### Invalid shift argument
157 shift ZZZ
158 # status: 1
159 # OK dash status: 2
160 # BUG mksh status: 0
161
162 ### get umask
163 umask | grep '[0-9]\+' # check for digits
164 # status: 0
165
166 ### set umask in octal
167 rm $TMP/umask-one $TMP/umask-two
168 umask 0002
169 echo one > $TMP/umask-one
170 umask 0022
171 echo two > $TMP/umask-two
172 stat -c '%a' $TMP/umask-one $TMP/umask-two
173 # status: 0
174 # stdout-json: "664\n644\n"
175 # stderr-json: ""
176
177 ### set umask symbolically
178 rm $TMP/umask-one $TMP/umask-two
179 echo one > $TMP/umask-one
180 umask g-w,o-w
181 echo two > $TMP/umask-two
182 stat -c '%a' $TMP/umask-one $TMP/umask-two
183 # status: 0
184 # stdout-json: "664\n644\n"
185 # stderr-json: ""
186