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