1 |
#!/usr/bin/env bash |
2 |
|
3 |
#### zero args: [ ] |
4 |
[ ] || echo false |
5 |
## stdout: false |
6 |
|
7 |
#### one arg: [ x ] where x is one of '=' '!' '(' ']' |
8 |
[ = ] |
9 |
echo status=$? |
10 |
[ ] ] |
11 |
echo status=$? |
12 |
[ '!' ] |
13 |
echo status=$? |
14 |
[ '(' ] |
15 |
echo status=$? |
16 |
## stdout-json: "status=0\nstatus=0\nstatus=0\nstatus=0\n" |
17 |
|
18 |
#### one arg: empty string is false. Equivalent to -n. |
19 |
test 'a' && echo true |
20 |
test '' || echo false |
21 |
## stdout-json: "true\nfalse\n" |
22 |
|
23 |
#### -a as unary operator (alias of -e) |
24 |
# NOT IMPLEMENTED FOR OSH, but could be later. See comment in core/id_kind.py. |
25 |
[ -a / ] |
26 |
echo status=$? |
27 |
[ -a /nonexistent ] |
28 |
echo status=$? |
29 |
## stdout-json: "status=0\nstatus=1\n" |
30 |
## N-I dash stdout-json: "status=2\nstatus=2\n" |
31 |
|
32 |
#### two args: -z with = ! ( ] |
33 |
[ -z = ] |
34 |
echo status=$? |
35 |
[ -z ] ] |
36 |
echo status=$? |
37 |
[ -z '!' ] |
38 |
echo status=$? |
39 |
[ -z '(' ] |
40 |
echo status=$? |
41 |
## stdout-json: "status=1\nstatus=1\nstatus=1\nstatus=1\n" |
42 |
|
43 |
#### three args |
44 |
[ foo = '' ] |
45 |
echo status=$? |
46 |
[ foo -a '' ] |
47 |
echo status=$? |
48 |
[ foo -o '' ] |
49 |
echo status=$? |
50 |
[ ! -z foo ] |
51 |
echo status=$? |
52 |
[ \( foo \) ] |
53 |
echo status=$? |
54 |
## stdout-json: "status=1\nstatus=1\nstatus=0\nstatus=0\nstatus=0\n" |
55 |
|
56 |
#### four args |
57 |
[ ! foo = foo ] |
58 |
echo status=$? |
59 |
[ \( -z foo \) ] |
60 |
echo status=$? |
61 |
## stdout-json: "status=1\nstatus=1\n" |
62 |
|
63 |
#### test with extra args is syntax error |
64 |
test -n x ] |
65 |
echo status=$? |
66 |
test -n x y |
67 |
echo status=$? |
68 |
## STDOUT: |
69 |
status=2 |
70 |
status=2 |
71 |
## END |
72 |
|
73 |
#### ] syntax errors |
74 |
[ |
75 |
echo status=$? |
76 |
test # not a syntax error |
77 |
echo status=$? |
78 |
[ -n x # missing ] |
79 |
echo status=$? |
80 |
[ -n x ] y # extra arg after ] |
81 |
echo status=$? |
82 |
[ -n x y # extra arg |
83 |
echo status=$? |
84 |
## STDOUT: |
85 |
status=2 |
86 |
status=1 |
87 |
status=2 |
88 |
status=2 |
89 |
status=2 |
90 |
## END |
91 |
|
92 |
#### -n |
93 |
test -n 'a' && echo true |
94 |
test -n '' || echo false |
95 |
## stdout-json: "true\nfalse\n" |
96 |
|
97 |
#### ! -a |
98 |
[ -z '' -a ! -z x ] |
99 |
echo status=$? |
100 |
## stdout: status=0 |
101 |
|
102 |
#### -o |
103 |
[ -z x -o ! -z x ] |
104 |
echo status=$? |
105 |
## stdout: status=0 |
106 |
|
107 |
#### ( ) |
108 |
[ -z '' -a '(' ! -z x ')' ] |
109 |
echo status=$? |
110 |
## stdout: status=0 |
111 |
|
112 |
#### ( ) ! -a -o with system version of [ |
113 |
command [ --version |
114 |
command [ -z '' -a '(' ! -z x ')' ] && echo true |
115 |
## stdout: true |
116 |
|
117 |
#### == is alias for = |
118 |
[ a = a ] && echo true |
119 |
[ a == a ] && echo true |
120 |
## stdout-json: "true\ntrue\n" |
121 |
## BUG dash stdout-json: "true\n" |
122 |
## BUG dash status: 2 |
123 |
|
124 |
#### == and = does not do glob |
125 |
[ abc = 'a*' ] |
126 |
echo status=$? |
127 |
[ abc == 'a*' ] |
128 |
echo status=$? |
129 |
## stdout-json: "status=1\nstatus=1\n" |
130 |
## N-I dash stdout-json: "status=1\nstatus=2\n" |
131 |
|
132 |
#### [ with op variable |
133 |
# OK -- parsed AFTER evaluation of vars |
134 |
op='=' |
135 |
[ a $op a ] && echo true |
136 |
[ a $op b ] || echo false |
137 |
## status: 0 |
138 |
## stdout-json: "true\nfalse\n" |
139 |
|
140 |
#### [ with unquoted empty var |
141 |
empty='' |
142 |
[ $empty = '' ] && echo true |
143 |
## status: 2 |
144 |
|
145 |
#### [ compare with literal -f |
146 |
# Hm this is the same |
147 |
var=-f |
148 |
[ $var = -f ] && echo true |
149 |
[ '-f' = $var ] && echo true |
150 |
## stdout-json: "true\ntrue\n" |
151 |
|
152 |
#### [ '(' foo ] is runtime syntax error |
153 |
[ '(' foo ] |
154 |
echo status=$? |
155 |
## stdout: status=2 |
156 |
|
157 |
#### -z '>' implies two token lookahead |
158 |
[ -z ] && echo true # -z is operand |
159 |
[ -z '>' ] || echo false # -z is operator |
160 |
[ -z '>' -- ] && echo true # -z is operand |
161 |
## stdout-json: "true\nfalse\ntrue\n" |
162 |
|
163 |
#### operator/operand ambiguity with ] |
164 |
# bash parses this as '-z' AND ']', which is true. It's a syntax error in |
165 |
# dash/mksh. |
166 |
[ -z -a ] ] |
167 |
echo status=$? |
168 |
## stdout: status=0 |
169 |
## OK mksh stdout: status=2 |
170 |
## OK dash stdout: status=2 |
171 |
|
172 |
#### operator/operand ambiguity with -a |
173 |
# bash parses it as '-z' AND '-a'. It's a syntax error in mksh but somehow a |
174 |
# runtime error in dash. |
175 |
[ -z -a -a ] |
176 |
echo status=$? |
177 |
## stdout: status=0 |
178 |
## OK mksh stdout: status=2 |
179 |
## OK dash stdout: status=1 |
180 |
|
181 |
#### -d |
182 |
test -d $TMP |
183 |
echo status=$? |
184 |
test -d $TMP/__nonexistent_Z_Z__ |
185 |
echo status=$? |
186 |
## stdout-json: "status=0\nstatus=1\n" |
187 |
|
188 |
#### -x |
189 |
rm -f $TMP/x |
190 |
echo 'echo hi' > $TMP/x |
191 |
test -x $TMP/x || echo 'no' |
192 |
chmod +x $TMP/x |
193 |
test -x $TMP/x && echo 'yes' |
194 |
test -x $TMP/__nonexistent__ || echo 'bad' |
195 |
## stdout-json: "no\nyes\nbad\n" |
196 |
|
197 |
#### -r |
198 |
echo '1' > $TMP/testr_yes |
199 |
echo '2' > $TMP/testr_no |
200 |
chmod -r $TMP/testr_no # remove read permission |
201 |
test -r $TMP/testr_yes && echo 'yes' |
202 |
test -r $TMP/testr_no || echo 'no' |
203 |
## stdout-json: "yes\nno\n" |
204 |
|
205 |
#### -w |
206 |
rm -f $TMP/testw_* |
207 |
echo '1' > $TMP/testw_yes |
208 |
echo '2' > $TMP/testw_no |
209 |
chmod -w $TMP/testw_no # remove write permission |
210 |
test -w $TMP/testw_yes && echo 'yes' |
211 |
test -w $TMP/testw_no || echo 'no' |
212 |
## stdout-json: "yes\nno\n" |
213 |
|
214 |
#### -h and -L test for symlink |
215 |
tmp=$TMP/builtin-test-1 |
216 |
mkdir -p $tmp |
217 |
touch $tmp/zz |
218 |
ln -s -f $tmp/zz $tmp/symlink |
219 |
ln -s -f $tmp/__nonexistent_ZZ__ $tmp/dangling |
220 |
test -L $tmp/zz || echo no |
221 |
test -h $tmp/zz || echo no |
222 |
test -f $tmp/symlink && echo is-file |
223 |
test -L $tmp/symlink && echo symlink |
224 |
test -h $tmp/symlink && echo symlink |
225 |
test -L $tmp/dangling && echo dangling |
226 |
test -h $tmp/dangling && echo dangling |
227 |
test -f $tmp/dangling || echo 'dangling is not file' |
228 |
## STDOUT: |
229 |
no |
230 |
no |
231 |
is-file |
232 |
symlink |
233 |
symlink |
234 |
dangling |
235 |
dangling |
236 |
dangling is not file |
237 |
## END |
238 |
|
239 |
#### -t 1 for stdout |
240 |
# There is no way to get a terminal in the test environment? |
241 |
[ -t 1 ] |
242 |
echo status=$? |
243 |
## stdout: status=1 |
244 |
|
245 |
#### [ -t invalid ] |
246 |
[ -t invalid ] |
247 |
echo status=$? |
248 |
## stdout: status=2 |
249 |
## BUG bash stdout: status=1 |
250 |
|
251 |
#### -ot and -nt |
252 |
touch -d 2017/12/31 $TMP/x |
253 |
touch -d 2018/01/01 > $TMP/y |
254 |
test $TMP/x -ot $TMP/y && echo 'older' |
255 |
test $TMP/x -nt $TMP/y || echo 'not newer' |
256 |
test $TMP/x -ot $TMP/x || echo 'not older than itself' |
257 |
test $TMP/x -nt $TMP/x || echo 'not newer than itself' |
258 |
## STDOUT: |
259 |
older |
260 |
not newer |
261 |
not older than itself |
262 |
not newer than itself |
263 |
## END |
264 |
|
265 |
#### [ a -eq b ] |
266 |
[ a -eq a ] |
267 |
echo status=$? |
268 |
## STDOUT: |
269 |
status=2 |
270 |
## END |
271 |
## BUG mksh STDOUT: |
272 |
status=0 |
273 |
## END |
274 |
|
275 |
#### test -s |
276 |
test -s __nonexistent |
277 |
echo status=$? |
278 |
touch $TMP/empty |
279 |
test -s $TMP/empty |
280 |
echo status=$? |
281 |
echo nonempty > $TMP/nonempty |
282 |
test -s $TMP/nonempty |
283 |
echo status=$? |
284 |
## STDOUT: |
285 |
status=1 |
286 |
status=1 |
287 |
status=0 |
288 |
## END |
289 |
|
290 |
#### test -b -c -S (block, character, socket) |
291 |
# NOTE: we do not have the "true" case |
292 |
|
293 |
echo -b |
294 |
test -b nonexistent |
295 |
echo status=$? |
296 |
test -b testdata |
297 |
echo status=$? |
298 |
|
299 |
echo -c |
300 |
test -c nonexistent |
301 |
echo status=$? |
302 |
test -c testdata |
303 |
echo status=$? |
304 |
|
305 |
echo -S |
306 |
test -S nonexistent |
307 |
echo status=$? |
308 |
test -S testdata |
309 |
echo status=$? |
310 |
|
311 |
## STDOUT: |
312 |
-b |
313 |
status=1 |
314 |
status=1 |
315 |
-c |
316 |
status=1 |
317 |
status=1 |
318 |
-S |
319 |
status=1 |
320 |
status=1 |
321 |
## END |
322 |
|
323 |
|
324 |
#### test -p named pipe |
325 |
mkfifo $TMP/fifo |
326 |
test -p $TMP/fifo |
327 |
echo status=$? |
328 |
|
329 |
test -p testdata |
330 |
echo status=$? |
331 |
|
332 |
## STDOUT: |
333 |
status=0 |
334 |
status=1 |
335 |
## END |
336 |
|
337 |
#### -G and -O for effective user ID and group ID |
338 |
|
339 |
test -O bin |
340 |
echo status=$? |
341 |
test -O __nonexistent__ |
342 |
echo status=$? |
343 |
|
344 |
test -G bin |
345 |
echo status=$? |
346 |
test -G __nonexistent__ |
347 |
echo status=$? |
348 |
|
349 |
## STDOUT: |
350 |
status=0 |
351 |
status=1 |
352 |
status=0 |
353 |
status=1 |
354 |
## END |
355 |
|
356 |
#### test -o for options |
357 |
# note: it's lame that the 'false' case is confused with the 'typo' case. |
358 |
# but checking for error code 2 is unlikely anyway. |
359 |
test -o nounset |
360 |
echo status=$? |
361 |
|
362 |
set -o nounset |
363 |
echo status=$? |
364 |
|
365 |
test -o _bad_name_ |
366 |
echo status=$? |
367 |
## STDOUT: |
368 |
status=1 |
369 |
status=0 |
370 |
status=1 |
371 |
## END |
372 |
## N-I dash STDOUT: |
373 |
status=2 |
374 |
status=0 |
375 |
status=2 |
376 |
## END |
377 |
|
378 |
#### -nt -ot |
379 |
[ present -nt absent ] || exit 1 |
380 |
[ absent -ot present ] || exit 2 |
381 |
## status: 1 |