1 #!/usr/bin/env bash
2 #
3 # NOTES:
4 # - osh is using the external binary.
5 # - because ! -a -o ( ) are the same, we can share logic with [[.
6
7 ### zero args: [ ]
8 [ ] || echo false
9 # stdout: false
10
11 ### one arg: [ x ] where x is one of '=' '!' '(' ']'
12 [ = ]
13 echo status=$?
14 [ ] ]
15 echo status=$?
16 [ '!' ]
17 echo status=$?
18 [ '(' ]
19 echo status=$?
20 # stdout-json: "status=0\nstatus=0\nstatus=0\nstatus=0\n"
21
22 ### one arg: empty string is false. Equivalent to -n.
23 test 'a' && echo true
24 test '' || echo false
25 # stdout-json: "true\nfalse\n"
26
27 ### -a as unary operator (alias of -e)
28 # NOT IMPLEMENTED FOR OSH, but could be later. See comment in core/id_kind.py.
29 [ -a / ]
30 echo status=$?
31 [ -a /nonexistent ]
32 echo status=$?
33 # stdout-json: "status=0\nstatus=1\n"
34 # N-I dash/osh stdout-json: "status=2\nstatus=2\n"
35
36 ### two args: -z with = ! ( ]
37 [ -z = ]
38 echo status=$?
39 [ -z ] ]
40 echo status=$?
41 [ -z '!' ]
42 echo status=$?
43 [ -z '(' ]
44 echo status=$?
45 # stdout-json: "status=1\nstatus=1\nstatus=1\nstatus=1\n"
46
47 ### three args
48 [ foo = '' ]
49 echo status=$?
50 [ foo -a '' ]
51 echo status=$?
52 [ foo -o '' ]
53 echo status=$?
54 [ ! -z foo ]
55 echo status=$?
56 [ \( foo \) ]
57 echo status=$?
58 # stdout-json: "status=1\nstatus=1\nstatus=0\nstatus=0\nstatus=0\n"
59
60 ### four args
61 [ ! foo = foo ]
62 echo status=$?
63 [ \( -z foo \) ]
64 echo status=$?
65 # stdout-json: "status=1\nstatus=1\n"
66
67 ### test with extra args is syntax error
68 test -n x ]
69 echo status=$?
70 test -n x y
71 echo status=$?
72 # stdout-json: "status=2\nstatus=2\n"
73
74 ### ] syntax errors
75 [ -n x # missing ]
76 echo status=$?
77 [ -n x ] y # extra arg after ]
78 echo status=$?
79 [ -n x y # extra arg
80 echo status=$?
81 # stdout-json: "status=2\nstatus=2\nstatus=2\n"
82
83 ### -n
84 test -n 'a' && echo true
85 test -n '' || echo false
86 # stdout-json: "true\nfalse\n"
87
88 ### ! -a -o
89 [ -z '' -a ! -z x ]
90 echo status=$?
91 # stdout: status=0
92
93 ### ( )
94 [ -z '' -a '(' ! -z x ')' ]
95 echo status=$?
96 # stdout: status=0
97
98 ### ( ) ! -a -o with system version of [
99 command [ --version
100 command [ -z '' -a '(' ! -z x ')' ] && echo true
101 # stdout: true
102
103 ### == is alias for =
104 [ a = a ] && echo true
105 [ a == a ] && echo true
106 # stdout-json: "true\ntrue\n"
107 # BUG dash stdout-json: "true\n"
108 # BUG dash status: 2
109
110 ### == and = does not do glob
111 [ abc = 'a*' ]
112 echo status=$?
113 [ abc == 'a*' ]
114 echo status=$?
115 # stdout-json: "status=1\nstatus=1\n"
116 # N-I dash stdout-json: "status=1\nstatus=2\n"
117
118 ### [ with op variable
119 # OK -- parsed AFTER evaluation of vars
120 op='='
121 [ a $op a ] && echo true
122 [ a $op b ] || echo false
123 # status: 0
124 # stdout-json: "true\nfalse\n"
125
126 ### [ with unquoted empty var
127 empty=''
128 [ $empty = '' ] && echo true
129 # status: 2
130
131 ### [ compare with literal -f
132 # Hm this is the same
133 var=-f
134 [ $var = -f ] && echo true
135 [ '-f' = $var ] && echo true
136 # stdout-json: "true\ntrue\n"
137
138 ### [ '(' foo ] is runtime syntax error
139 [ '(' foo ]
140 echo status=$?
141 # stdout: status=2
142
143 ### -z '>' implies two token lookahead
144 [ -z ] && echo true # -z is operand
145 [ -z '>' ] || echo false # -z is operator
146 [ -z '>' -- ] && echo true # -z is operand
147 # stdout-json: "true\nfalse\ntrue\n"
148
149 ### operator/operand ambiguity with ]
150 # bash parses this as '-z' AND ']', which is true. It's a syntax error in
151 # dash/mksh.
152 [ -z -a ] ]
153 echo status=$?
154 # stdout: status=0
155 # OK mksh stdout: status=2
156 # OK dash stdout: status=2
157
158 ### operator/operand ambiguity with -a
159 # bash parses it as '-z' AND '-a'. It's a syntax error in mksh but somehow a
160 # runtime error in dash.
161 [ -z -a -a ]
162 echo status=$?
163 # stdout: status=0
164 # OK mksh stdout: status=2
165 # OK dash stdout: status=1
166
167 ### -d
168 test -d $TMP
169 echo status=$?
170 test -d $TMP/__nonexistent_Z_Z__
171 echo status=$?
172 # stdout-json: "status=0\nstatus=1\n"
173
174 ### -x
175 rm -f $TMP/x
176 echo 'echo hi' > $TMP/x
177 test -x $TMP/x || echo 'no'
178 chmod +x $TMP/x
179 test -x $TMP/x && echo 'yes'
180 test -x $TMP/__nonexistent__ || echo 'bad'
181 # stdout-json: "no\nyes\nbad\n"