1 #!/usr/bin/env bash
2 #
3 # Test set flags, sh flags.
4
5 #### $- with -c
6 # dash's behavior seems most sensible here?
7 $SH -o nounset -c 'echo $-'
8 ## stdout: u
9 ## OK bash stdout: huBc
10 ## OK mksh stdout: uhc
11 ## status: 0
12
13 #### $- with pipefail
14 set -o pipefail -o nounset
15 echo $-
16 ## stdout: u
17 ## status: 0
18 ## OK bash stdout: huBs
19 ## OK mksh stdout: ush
20 ## N-I dash stdout-json: ""
21 ## N-I dash status: 2
22
23 #### $- with interactive shell
24 $SH -c 'echo $-' | grep i || echo FALSE
25 $SH -i -c 'echo $-' | grep -q i && echo TRUE
26 ## STDOUT:
27 FALSE
28 TRUE
29 ## END
30
31 #### sh -c
32 $SH -c 'echo hi'
33 ## stdout: hi
34 ## status: 0
35
36 #### empty -c input
37 # had a bug here
38 $SH -c ''
39 ## stdout-json: ""
40 ## status: 0
41
42 #### empty stdin
43 # had a bug here
44 echo -n '' | $SH
45 ## stdout-json: ""
46 ## status: 0
47
48 #### args are passed
49 $SH -c 'argv.py "$@"' dummy a b
50 ## stdout: ['a', 'b']
51
52 #### args that look like flags are passed after script
53 script=$TMP/sh1.sh
54 echo 'argv.py "$@"' > $script
55 chmod +x $script
56 $SH $script --help --help -h
57 ## stdout: ['--help', '--help', '-h']
58
59 #### args that look like flags are passed after -c
60 $SH -c 'argv.py "$@"' --help --help -h
61 ## stdout: ['--help', '-h']
62
63 #### pass short options on command line
64 $SH -e -c 'false; echo status=$?'
65 ## stdout-json: ""
66 ## status: 1
67
68 #### pass long options on command line
69 $SH -o errexit -c 'false; echo status=$?'
70 ## stdout-json: ""
71 ## status: 1
72
73 #### can continue after unknown option
74 # dash and mksh make this a fatal error no matter what.
75 set -o errexit
76 set -o STRICT || true # unknown option
77 echo hello
78 ## stdout: hello
79 ## status: 0
80 ## BUG dash/mksh stdout-json: ""
81 ## BUG dash status: 2
82 ## BUG mksh status: 1
83
84 #### set with both options and argv
85 set -o errexit a b c
86 echo "$@"
87 false
88 echo done
89 ## stdout: a b c
90 ## status: 1
91
92 #### set -o vi/emacs
93 set -o vi
94 echo $?
95 set -o emacs
96 echo $?
97 ## STDOUT:
98 0
99 0
100 ## END
101
102 #### nounset
103 echo "[$unset]"
104 set -o nounset
105 echo "[$unset]"
106 echo end # never reached
107 ## stdout: []
108 ## status: 1
109 ## OK dash status: 2
110
111 #### -u is nounset
112 echo "[$unset]"
113 set -u
114 echo "[$unset]"
115 echo end # never reached
116 ## stdout: []
117 ## status: 1
118 ## OK dash status: 2
119
120 #### nounset with "$@"
121 set a b c
122 set -u # shouldn't touch argv
123 echo "$@"
124 ## stdout: a b c
125
126 #### set -u -- clears argv
127 set a b c
128 set -u -- # shouldn't touch argv
129 echo "$@"
130 ## stdout:
131
132 #### set -u -- x y z
133 set a b c
134 set -u -- x y z
135 echo "$@"
136 ## stdout: x y z
137
138 #### reset option with long flag
139 set -o errexit
140 set +o errexit
141 echo "[$unset]"
142 ## stdout: []
143 ## status: 0
144
145 #### reset option with short flag
146 set -u
147 set +u
148 echo "[$unset]"
149 ## stdout: []
150 ## status: 0
151
152 #### set -eu (flag parsing)
153 set -eu
154 echo "[$unset]"
155 echo status=$?
156 ## stdout-json: ""
157 ## status: 1
158 ## OK dash status: 2
159
160 #### -n for no execution (useful with --ast-output)
161 # NOTE: set +n doesn't work because nothing is executed!
162 echo 1
163 set -n
164 echo 2
165 set +n
166 echo 3
167 ## stdout-json: "1\n"
168 ## status: 0
169
170 #### pipefail
171 # NOTE: the sleeps are because osh can fail non-deterministically because of a
172 # bug. Same problem as PIPESTATUS.
173 { sleep 0.01; exit 9; } | { sleep 0.02; exit 2; } | { sleep 0.03; exit 0; }
174 echo $?
175 set -o pipefail
176 { sleep 0.01; exit 9; } | { sleep 0.02; exit 2; } | { sleep 0.03; exit 0; }
177 echo $?
178 ## stdout-json: "0\n2\n"
179 ## status: 0
180 ## N-I dash stdout-json: "0\n"
181 ## N-I dash status: 2
182
183 #### shopt -p -o
184 shopt -po nounset
185 set -u
186 shopt -po nounset
187 ## stdout-json: "set +o nounset\nset -o nounset\n"
188 ## N-I dash/mksh stdout-json: ""
189 ## N-I dash/mksh status: 127
190
191 #### shopt -p
192 shopt -p nullglob
193 shopt -s nullglob
194 shopt -p nullglob
195 ## stdout-json: "shopt -u nullglob\nshopt -s nullglob\n"
196 ## N-I dash/mksh stdout-json: ""
197 ## N-I dash/mksh status: 127
198
199 #### noclobber off
200 set -o errexit
201 echo foo > $TMP/can-clobber
202 set +C
203 echo foo > $TMP/can-clobber
204 set +o noclobber
205 echo foo > $TMP/can-clobber
206 cat $TMP/can-clobber
207 ## stdout: foo
208
209 #### noclobber on
210 # Not implemented yet.
211 rm $TMP/no-clobber
212 set -C
213 echo foo > $TMP/no-clobber
214 echo $?
215 echo foo > $TMP/no-clobber
216 echo $?
217 ## stdout-json: "0\n1\n"
218 ## OK dash stdout-json: "0\n2\n"
219
220 #### SHELLOPTS is updated when options are changed
221 echo $SHELLOPTS | grep -q xtrace
222 echo $?
223 set -x
224 echo $SHELLOPTS | grep -q xtrace
225 echo $?
226 set +x
227 echo $SHELLOPTS | grep -q xtrace
228 echo $?
229 ## stdout-json: "1\n0\n1\n"
230 ## N-I dash/mksh stdout-json: "1\n1\n1\n"
231
232 #### SHELLOPTS is readonly
233 SHELLOPTS=x
234 echo status=$?
235 ## stdout: status=1
236 ## N-I dash/mksh stdout: status=0
237
238 #### set -o lists options
239 set -o | grep set
240 ## status: 0
241
242 #### set without args lists variables
243 set | grep PWD
244 ## status: 0
245
246 #### shopt -q
247 shopt -q nullglob
248 echo nullglob=$?
249
250 # set it
251 shopt -s nullglob
252
253 shopt -q nullglob
254 echo nullglob=$?
255
256 shopt -q nullglob failglob
257 echo nullglob,failglob=$?
258
259 # set it
260 shopt -s failglob
261 shopt -q nullglob failglob
262 echo nullglob,failglob=$?
263
264 ## STDOUT:
265 nullglob=1
266 nullglob=0
267 nullglob,failglob=1
268 nullglob,failglob=0
269 ## END
270 ## N-I dash/mksh STDOUT:
271 nullglob=127
272 nullglob=127
273 nullglob,failglob=127
274 nullglob,failglob=127
275 ## END
276
277 #### shopt -q invalid
278 shopt -q invalidZZ
279 echo invalidZZ=$?
280 ## STDOUT:
281 invalidZZ=2
282 ## END
283 ## OK bash STDOUT:
284 invalidZZ=1
285 ## END
286 ## N-I dash/mksh STDOUT:
287 invalidZZ=127
288 ## END
289