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