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