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-json: "status=0\nstatus=0\nstatus=0\nstatus=0\n"
17
18 ### one arg: empty string is false. Equivalent to -n.
19 test 'a' && echo true
20 test '' || echo false
21 # stdout-json: "true\nfalse\n"
22
23 ### -a as unary operator (alias of -e)
24 # NOT IMPLEMENTED FOR OSH, but could be later. See comment in core/id_kind.py.
25 [ -a / ]
26 echo status=$?
27 [ -a /nonexistent ]
28 echo status=$?
29 # stdout-json: "status=0\nstatus=1\n"
30 # N-I dash stdout-json: "status=2\nstatus=2\n"
31
32 ### two args: -z with = ! ( ]
33 [ -z = ]
34 echo status=$?
35 [ -z ] ]
36 echo status=$?
37 [ -z '!' ]
38 echo status=$?
39 [ -z '(' ]
40 echo status=$?
41 # stdout-json: "status=1\nstatus=1\nstatus=1\nstatus=1\n"
42
43 ### three args
44 [ foo = '' ]
45 echo status=$?
46 [ foo -a '' ]
47 echo status=$?
48 [ foo -o '' ]
49 echo status=$?
50 [ ! -z foo ]
51 echo status=$?
52 [ \( foo \) ]
53 echo status=$?
54 # stdout-json: "status=1\nstatus=1\nstatus=0\nstatus=0\nstatus=0\n"
55
56 ### four args
57 [ ! foo = foo ]
58 echo status=$?
59 [ \( -z foo \) ]
60 echo status=$?
61 # stdout-json: "status=1\nstatus=1\n"
62
63 ### test with extra args is syntax error
64 test -n x ]
65 echo status=$?
66 test -n x y
67 echo status=$?
68 ## STDOUT:
69 status=2
70 status=2
71 ## END
72
73 ### ] syntax errors
74 [
75 echo status=$?
76 test # not a syntax error
77 echo status=$?
78 [ -n x # missing ]
79 echo status=$?
80 [ -n x ] y # extra arg after ]
81 echo status=$?
82 [ -n x y # extra arg
83 echo status=$?
84 ## STDOUT:
85 status=2
86 status=1
87 status=2
88 status=2
89 status=2
90 ## END
91
92 ### -n
93 test -n 'a' && echo true
94 test -n '' || echo false
95 # stdout-json: "true\nfalse\n"
96
97 ### ! -a
98 [ -z '' -a ! -z x ]
99 echo status=$?
100 # stdout: status=0
101
102 ### -o
103 [ -z x -o ! -z x ]
104 echo status=$?
105 # stdout: status=0
106
107 ### ( )
108 [ -z '' -a '(' ! -z x ')' ]
109 echo status=$?
110 # stdout: status=0
111
112 ### ( ) ! -a -o with system version of [
113 command [ --version
114 command [ -z '' -a '(' ! -z x ')' ] && echo true
115 # stdout: true
116
117 ### == is alias for =
118 [ a = a ] && echo true
119 [ a == a ] && echo true
120 # stdout-json: "true\ntrue\n"
121 # BUG dash stdout-json: "true\n"
122 # BUG dash status: 2
123
124 ### == and = does not do glob
125 [ abc = 'a*' ]
126 echo status=$?
127 [ abc == 'a*' ]
128 echo status=$?
129 # stdout-json: "status=1\nstatus=1\n"
130 # N-I dash stdout-json: "status=1\nstatus=2\n"
131
132 ### [ with op variable
133 # OK -- parsed AFTER evaluation of vars
134 op='='
135 [ a $op a ] && echo true
136 [ a $op b ] || echo false
137 # status: 0
138 # stdout-json: "true\nfalse\n"
139
140 ### [ with unquoted empty var
141 empty=''
142 [ $empty = '' ] && echo true
143 # status: 2
144
145 ### [ compare with literal -f
146 # Hm this is the same
147 var=-f
148 [ $var = -f ] && echo true
149 [ '-f' = $var ] && echo true
150 # stdout-json: "true\ntrue\n"
151
152 ### [ '(' foo ] is runtime syntax error
153 [ '(' foo ]
154 echo status=$?
155 # stdout: status=2
156
157 ### -z '>' implies two token lookahead
158 [ -z ] && echo true # -z is operand
159 [ -z '>' ] || echo false # -z is operator
160 [ -z '>' -- ] && echo true # -z is operand
161 # stdout-json: "true\nfalse\ntrue\n"
162
163 ### operator/operand ambiguity with ]
164 # bash parses this as '-z' AND ']', which is true. It's a syntax error in
165 # dash/mksh.
166 [ -z -a ] ]
167 echo status=$?
168 # stdout: status=0
169 # OK mksh stdout: status=2
170 # OK dash stdout: status=2
171
172 ### operator/operand ambiguity with -a
173 # bash parses it as '-z' AND '-a'. It's a syntax error in mksh but somehow a
174 # runtime error in dash.
175 [ -z -a -a ]
176 echo status=$?
177 # stdout: status=0
178 # OK mksh stdout: status=2
179 # OK dash stdout: status=1
180
181 ### -d
182 test -d $TMP
183 echo status=$?
184 test -d $TMP/__nonexistent_Z_Z__
185 echo status=$?
186 # stdout-json: "status=0\nstatus=1\n"
187
188 ### -x
189 rm -f $TMP/x
190 echo 'echo hi' > $TMP/x
191 test -x $TMP/x || echo 'no'
192 chmod +x $TMP/x
193 test -x $TMP/x && echo 'yes'
194 test -x $TMP/__nonexistent__ || echo 'bad'
195 # stdout-json: "no\nyes\nbad\n"
196
197 ### -r
198 echo '1' > $TMP/testr_yes
199 echo '2' > $TMP/testr_no
200 chmod -r $TMP/testr_no # remove read permission
201 test -r $TMP/testr_yes && echo 'yes'
202 test -r $TMP/testr_no || echo 'no'
203 # stdout-json: "yes\nno\n"
204
205 ### -w
206 rm -f $TMP/testw_*
207 echo '1' > $TMP/testw_yes
208 echo '2' > $TMP/testw_no
209 chmod -w $TMP/testw_no # remove write permission
210 test -w $TMP/testw_yes && echo 'yes'
211 test -w $TMP/testw_no || echo 'no'
212 # stdout-json: "yes\nno\n"
213
214 ### -h and -L test for symlink
215 touch $TMP/zz
216 ln -s -f $TMP/zz $TMP/symlink
217 ln -s -f $TMP/__nonexistent_ZZ__ $TMP/dangling
218 test -L $TMP/zz || echo no
219 test -h $TMP/zz || echo no
220 test -f $TMP/symlink && echo is-file
221 test -L $TMP/symlink && echo symlink
222 test -h $TMP/symlink && echo symlink
223 test -L $TMP/dangling && echo dangling
224 test -h $TMP/dangling && echo dangling
225 test -f $TMP/dangling || echo 'dangling is not file'
226 ## STDOUT:
227 no
228 no
229 is-file
230 symlink
231 symlink
232 dangling
233 dangling
234 dangling is not file
235 ## END
236
237 ### -t 1 for stdout
238 # There isn't way to get a terminal in the test environment?
239 [ -t 1 ]
240 echo status=$?
241 ## stdout: status=1
242
243 ### [ -t invalid ]
244 [ -t invalid ]
245 echo status=$?
246 ## stdout: status=2
247 ## BUG bash stdout: status=1
248
249 ### -ot and -nt
250 touch -d 2017/12/31 $TMP/x
251 touch -d 2018/01/01 > $TMP/y
252 test $TMP/x -ot $TMP/y && echo 'older'
253 test $TMP/x -nt $TMP/y || echo 'not newer'
254 test $TMP/x -ot $TMP/x || echo 'not older than itself'
255 test $TMP/x -nt $TMP/x || echo 'not newer than itself'
256 ## STDOUT:
257 older
258 not newer
259 not older than itself
260 not newer than itself
261 ## END