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
|
582 |
|
583 | #### bug from pnut: negative number $((-1))
|
584 |
|
585 | # https://lobste.rs/s/lplim1/design_self_compiling_c_transpiler#c_km2ywc
|
586 |
|
587 | [ $((-42)) -le 0 ]
|
588 | echo status=$?
|
589 |
|
590 | [ $((-1)) -le 0 ]
|
591 | echo status=$?
|
592 |
|
593 | echo
|
594 |
|
595 | [ -1 -le 0 ]
|
596 | echo status=$?
|
597 |
|
598 | [ -42 -le 0 ]
|
599 | echo status=$?
|
600 |
|
601 | echo
|
602 |
|
603 | test -1 -le 0
|
604 | echo status=$?
|
605 |
|
606 | test -42 -le 0
|
607 | echo status=$?
|
608 |
|
609 | ## STDOUT:
|
610 | status=0
|
611 | status=0
|
612 |
|
613 | status=0
|
614 | status=0
|
615 |
|
616 | status=0
|
617 | status=0
|
618 | ## END
|
619 |
|
620 | #### negative octal numbers, etc.
|
621 |
|
622 | # zero
|
623 | [ -0 -eq 0 ]
|
624 | echo zero=$?
|
625 |
|
626 | # octal numbers can be negative
|
627 | [ -0123 -eq -83 ]
|
628 | echo octal=$?
|
629 |
|
630 | # hex doesn't have negative numbers?
|
631 | [ -0xff -eq -255 ]
|
632 | echo hex=$?
|
633 |
|
634 | # base N doesn't either
|
635 | [ -64#a -eq -10 ]
|
636 | echo baseN=$?
|
637 |
|
638 | ## STDOUT:
|
639 | zero=0
|
640 | octal=1
|
641 | hex=2
|
642 | baseN=2
|
643 | ## END
|
644 |
|
645 | #### More negative numbers
|
646 | case $SH in dash) exit ;; esac
|
647 |
|
648 | [[ -1 -le 0 ]]
|
649 | echo status=$?
|
650 |
|
651 | [[ $((-1)) -le 0 ]]
|
652 | echo status=$?
|
653 |
|
654 | ## STDOUT:
|
655 | status=0
|
656 | status=0
|
657 | ## END
|
658 |
|
659 | ## N-I dash STDOUT:
|
660 | ## END
|
661 |
|
662 | #### No octal, hex, base N conversion - leading 0 is a regular decimal
|
663 |
|
664 | # arithmetic has octal conversion
|
665 | echo $(( 073 ))
|
666 | echo $(( -073 ))
|
667 |
|
668 | echo
|
669 |
|
670 | # Bracket does NOT have octal conversion! That is annoying.
|
671 | [ 073 -eq 73 ]
|
672 | echo status=$?
|
673 |
|
674 | [ -073 -eq -73 ]
|
675 | echo status=$?
|
676 |
|
677 | echo
|
678 |
|
679 | [ 0xff -eq 255 ]
|
680 | echo hex=$?
|
681 | [ 64#a -eq 10 ]
|
682 | echo baseN=$?
|
683 |
|
684 | ## STDOUT:
|
685 | 59
|
686 | -59
|
687 |
|
688 | status=0
|
689 | status=0
|
690 |
|
691 | hex=2
|
692 | baseN=2
|
693 | ## END
|
694 |
|
695 | ## BUG mksh STDOUT:
|
696 | 73
|
697 | -73
|
698 |
|
699 | status=0
|
700 | status=0
|
701 |
|
702 | hex=2
|
703 | baseN=2
|
704 | ## END
|
705 |
|
706 | #### Looks like octal, but digit is too big
|
707 |
|
708 | # arithmetic has octal conversion
|
709 | echo $(( 083 ))
|
710 | echo status=$?
|
711 |
|
712 | echo $(( -083 ))
|
713 | echo status=$?
|
714 |
|
715 | echo
|
716 |
|
717 | # Bracket does NOT have octal conversion! That is annoying.
|
718 | [ 083 -eq 83 ]
|
719 | echo status=$?
|
720 |
|
721 | [ -083 -eq -83 ]
|
722 | echo status=$?
|
723 |
|
724 | ## status: 1
|
725 | ## STDOUT:
|
726 | ## END
|
727 |
|
728 | ## OK dash status: 2
|
729 |
|
730 | ## OK bash status: 0
|
731 | ## OK bash STDOUT:
|
732 | status=1
|
733 | status=1
|
734 |
|
735 | status=0
|
736 | status=0
|
737 | ## END
|
738 |
|
739 | ## OK mksh status: 0
|
740 | ## OK mksh STDOUT:
|
741 | 83
|
742 | status=0
|
743 | -83
|
744 | status=0
|
745 |
|
746 | status=0
|
747 | status=0
|
748 | ## END
|
749 |
|
750 | #### no recursive arith [ 1+2 -eq 3 ]
|
751 |
|
752 | [ 1+2 -eq 3 ]
|
753 | echo status=$?
|
754 |
|
755 | s='1+2'
|
756 | [ "$s" -eq 3 ]
|
757 | echo status=$?
|
758 |
|
759 | ## STDOUT:
|
760 | status=2
|
761 | status=2
|
762 | ## END
|
763 |
|
764 | ## BUG mksh STDOUT:
|
765 | status=0
|
766 | status=0
|
767 | ## END
|