1 ## oils_failures_allowed: 0
2 ## compare_shells: bash-4.4 mksh
3
4 # NOTE: zsh passes about half, and fails about half. It supports a subset of
5 # [[ I guess.
6
7 #### [[ glob matching, [[ has no glob expansion
8 [[ foo.py == *.py ]] && echo true
9 [[ foo.p == *.py ]] || echo false
10 ## STDOUT:
11 true
12 false
13 ## END
14
15 #### [[ glob matching with escapes
16 [[ 'foo.*' == *."*" ]] && echo true
17 # note that the pattern arg to fnmatch should be '*.\*'
18 ## stdout: true
19
20 #### equality
21 [[ '*.py' == '*.py' ]] && echo true
22 [[ foo.py == '*.py' ]] || echo false
23 ## STDOUT:
24 true
25 false
26 ## END
27
28 #### [[ glob matching with unquoted var
29 pat=*.py
30 [[ foo.py == $pat ]] && echo true
31 [[ foo.p == $pat ]] || echo false
32 ## STDOUT:
33 true
34 false
35 ## END
36
37 #### [[ regex matching
38 # mksh doesn't have this syntax of regex matching. I guess it comes from perl?
39 regex='.*\.py'
40 [[ foo.py =~ $regex ]] && echo true
41 [[ foo.p =~ $regex ]] || echo false
42 ## STDOUT:
43 true
44 false
45 ## END
46 ## N-I mksh stdout-json: ""
47 ## N-I mksh status: 1
48
49 #### [[ regex syntax error
50 # hm, it doesn't show any error, but it exits 2.
51 [[ foo.py =~ * ]] && echo true
52 ## status: 2
53 ## N-I mksh status: 1
54
55 #### [[ has no word splitting
56 var='one two'
57 [[ 'one two' == $var ]] && echo true
58 ## stdout: true
59
60 #### [[ has quote joining
61 var='one two'
62 [[ 'one 'tw"o" == $var ]] && echo true
63 ## stdout: true
64
65 #### [[ empty string is false
66 [[ 'a' ]] && echo true
67 [[ '' ]] || echo false
68 ## STDOUT:
69 true
70 false
71 ## END
72
73 #### && chain
74 [[ t && t && '' ]] || echo false
75 ## stdout: false
76
77 #### || chain
78 [[ '' || '' || t ]] && echo true
79 ## stdout: true
80
81 #### [[ compound expressions
82 # Notes on whitespace:
83 # - 1 and == need space seprating them, but ! and ( don't.
84 # - [[ needs whitesapce after it, but ]] doesn't need whitespace before it!
85 [[ ''||! (1 == 2)&&(2 == 2)]] && echo true
86 ## stdout: true
87
88 # NOTE on the two cases below. We're comparing
89 # (a || b) && c vs. a || (b && c)
90 #
91 # a = true, b = false, c = false is an example where they are different.
92 # && and || have precedence inside
93
94 #### precedence of && and || inside [[
95 [[ True || '' && '' ]] && echo true
96 ## stdout: true
97
98 #### precedence of && and || in a command context
99 if test True || test '' && test ''; then
100 echo YES
101 else
102 echo "NO precedence"
103 fi
104 ## stdout: NO precedence
105
106 # http://tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS
107
108 #### Octal literals with -eq
109 shopt -u strict_arith || true
110 decimal=15
111 octal=017 # = 15 (decimal)
112 [[ $decimal -eq $octal ]] && echo true
113 [[ $decimal -eq ZZZ$octal ]] || echo false
114 ## STDOUT:
115 true
116 false
117 ## END
118 ## N-I mksh stdout: false
119 # mksh doesn't implement this syntax for literals.
120
121 #### Hex literals with -eq
122 shopt -u strict_arith || true
123 decimal=15
124 hex=0x0f # = 15 (decimal)
125 [[ $decimal -eq $hex ]] && echo true
126 [[ $decimal -eq ZZZ$hex ]] || echo false
127 ## STDOUT:
128 true
129 false
130 ## END
131 ## N-I mksh stdout: false
132
133 # TODO: Add tests for this
134 # https://www.gnu.org/software/bash/manual/bash.html#Bash-Conditional-Expressions
135 # When used with [[, the ‘<’ and ‘>’ operators sort lexicographically using the
136 # current locale. The test command uses ASCII ordering.
137
138 #### > on strings
139 # NOTE: < doesn't need space, even though == does? That's silly.
140 [[ b>a ]] && echo true
141 [[ b<a ]] || echo false
142 ## STDOUT:
143 true
144 false
145 ## END
146
147 #### != on strings
148 # NOTE: b!=a does NOT work
149 [[ b != a ]] && echo true
150 [[ a != a ]] || echo false
151 ## STDOUT:
152 true
153 false
154 ## END
155
156 #### -eq on strings
157 # This is lame behavior: it does a conversion to 0 first for any string
158 shopt -u strict_arith || true
159 [[ a -eq a ]] && echo true
160 [[ a -eq b ]] && echo true
161 ## STDOUT:
162 true
163 true
164 ## END
165
166 #### [[ compare with literal -f (compare with test-builtin.test.sh)
167 var=-f
168 [[ $var == -f ]] && echo true
169 [[ '-f' == $var ]] && echo true
170 ## STDOUT:
171 true
172 true
173 ## END
174
175 #### [[ with op variable (compare with test-builtin.test.sh)
176 # Parse error -- parsed BEFORE evaluation of vars
177 op='=='
178 [[ a $op a ]] && echo true
179 [[ a $op b ]] || echo false
180 ## status: 2
181 ## OK mksh status: 1
182
183 #### [[ with unquoted empty var (compare with test-builtin.test.sh)
184 empty=''
185 [[ $empty == '' ]] && echo true
186 ## stdout: true
187
188 #### [[ at runtime doesn't work
189 dbracket=[[
190 $dbracket foo == foo ]]
191 ## status: 127
192
193 #### [[ with env prefix doesn't work
194 FOO=bar [[ foo == foo ]]
195 ## status: 127
196
197 #### [[ over multiple lines is OK
198 # Hm it seems you can't split anywhere?
199 [[ foo == foo
200 && bar == bar
201 ]] && echo true
202 ## status: 0
203 ## STDOUT:
204 true
205 ## END
206
207 #### Argument that looks like a real operator
208 [[ -f < ]] && echo 'should be parse error'
209 ## status: 2
210 ## OK mksh status: 1
211
212 #### User array compared to "$@" (broken unless shopt -s strict_array)
213 # Both are coerced to string! It treats it more like an UNQUOTED ${a[@]}.
214
215 a=('1 3' 5)
216 b=(1 2 3)
217 set -- 1 '3 5'
218 [[ "$@" = "${a[@]}" ]] && echo true
219 [[ "$@" = "${b[@]}" ]] || echo false
220 ## STDOUT:
221 true
222 false
223 ## END
224
225 #### Array coerces to string (shopt -s strict_array to disallow)
226 a=('1 3' 5)
227 [[ '1 3 5' = "${a[@]}" ]] && echo true
228 [[ '1 3 4' = "${a[@]}" ]] || echo false
229 ## STDOUT:
230 true
231 false
232 ## END
233
234 #### (( array1 == array2 )) doesn't work
235 a=('1 3' 5)
236 b=('1 3' 5)
237 c=('1' '3 5')
238 d=('1' '3 6')
239
240 # shells EXPAND a and b first
241 (( a == b ))
242 echo status=$?
243
244 (( a == c ))
245 echo status=$?
246
247 (( a == d ))
248 echo status=$?
249
250 ## stdout-json: ""
251 ## status: 1
252 ## BUG bash STDOUT:
253 status=1
254 status=1
255 status=1
256 ## END
257 ## BUG bash status: 0
258
259 #### Quotes don't matter in comparison
260 [[ '3' = 3 ]] && echo true
261 [[ '3' -eq 3 ]] && echo true
262 ## STDOUT:
263 true
264 true
265 ## END
266
267 #### -eq does dynamic arithmetic parsing (not supported in OSH)
268 [[ 1+2 -eq 3 ]] && echo true
269 expr='1+2'
270 [[ $expr -eq 3 ]] && echo true # must be dynamically parsed
271 ## STDOUT:
272 true
273 true
274 ## END
275
276 #### -eq coercion produces weird results
277 shopt -u strict_arith || true
278 [[ '' -eq 0 ]] && echo true
279 ## stdout: true
280
281 #### [[ '(' ]] is treated as literal
282 [[ '(' ]]
283 echo status=$?
284 ## stdout: status=0
285
286 #### [[ '(' foo ]] is syntax error
287 [[ '(' foo ]]
288 echo status=$?
289 ## status: 2
290 ## OK mksh status: 1
291
292 #### empty ! is treated as literal
293 [[ '!' ]]
294 echo status=$?
295 ## stdout: status=0
296
297 #### [[ -z ]] is syntax error
298 [[ -z ]]
299 echo status=$?
300 ## status: 2
301 ## OK mksh status: 1
302
303 #### [[ -z '>' ]]
304 [[ -z '>' ]] || echo false # -z is operator
305 ## stdout: false
306
307 #### [[ -z '>' a ]] is syntax error
308 [[ -z '>' -- ]]
309 echo status=$?
310 ## status: 2
311 ## OK mksh status: 1
312
313 #### test whether ']]' is empty
314 [[ ']]' ]]
315 echo status=$?
316 ## status: 0
317
318 #### [[ ]] is syntax error
319 [[ ]]
320 echo status=$?
321 ## stdout-json: ""
322 ## status: 2
323 ## OK mksh status: 1
324
325 #### [[ && ]] is syntax error
326 [[ && ]]
327 echo status=$?
328 ## stdout-json: ""
329 ## status: 2
330 ## OK mksh status: 1
331
332 #### [[ a 3< b ]] doesn't work (bug regression)
333 [[ a 3< b ]]
334 echo status=$?
335 [[ a 3> b ]]
336 echo status=$?
337 ## status: 2
338
339 # Hm these shells use the same redirect trick that OSH used to!
340
341 ## BUG mksh/zsh status: 0
342 ## BUG mksh/zsh STDOUT:
343 status=0
344 status=1
345 ## END
346
347 #### tilde expansion in [[
348 HOME=/home/bob
349 [[ ~ == /home/bob ]]
350 echo status=$?
351
352 [[ ~ == */bob ]]
353 echo status=$?
354
355 [[ ~ == */z ]]
356 echo status=$?
357
358 ## STDOUT:
359 status=0
360 status=0
361 status=1
362 ## END
363
364 #### more tilde expansion
365 [[ ~ ]]
366 echo status=$?
367 HOME=''
368 [[ ~ ]]
369 echo status=$?
370 [[ -n ~ ]]
371 echo unary=$?
372
373 [[ ~ == ~ ]]
374 echo status=$?
375
376 [[ $HOME == ~ ]]
377 echo fnmatch=$?
378 [[ ~ == $HOME ]]
379 echo fnmatch=$?
380
381 ## STDOUT:
382 status=0
383 status=1
384 unary=1
385 status=0
386 fnmatch=0
387 fnmatch=0
388 ## END
389
390 #### tilde expansion with =~ (confusing)
391 case $SH in mksh) exit ;; esac
392
393 HOME=foo
394 [[ ~ =~ $HOME ]]
395 echo regex=$?
396 [[ $HOME =~ ~ ]]
397 echo regex=$?
398
399 HOME='^a$' # looks like regex
400 [[ ~ =~ $HOME ]]
401 echo regex=$?
402 [[ $HOME =~ ~ ]]
403 echo regex=$?
404
405 ## STDOUT:
406 regex=0
407 regex=0
408 regex=1
409 regex=0
410 ## END
411 ## OK zsh STDOUT:
412 regex=0
413 regex=0
414 regex=1
415 regex=1
416 ## END
417 ## N-I mksh stdout-json: ""
418
419 #### [[ ]] with redirect
420 [[ $(stdout_stderr.py) == STDOUT ]] 2>$TMP/x.txt
421 echo $?
422 echo --
423 cat $TMP/x.txt
424 ## STDOUT:
425 0
426 --
427 STDERR
428 ## END
429
430 #### special chars
431 [[ ^ == ^ ]]
432 echo caret $?
433 [[ '!' == ! ]]
434 echo bang $?
435 ## STDOUT:
436 caret 0
437 bang 0
438 ## END
439
440
441 #### \(\) in pattern (regression)
442 if [[ 'foo()' == *\(\) ]]; then echo match1; fi
443 if [[ 'foo()' == *'()' ]]; then echo match2; fi
444 if [[ 'foo()' == '*()' ]]; then echo match3; fi
445
446 shopt -s extglob
447
448 if [[ 'foo()' == *\(\) ]]; then echo match1; fi
449 if [[ 'foo()' == *'()' ]]; then echo match2; fi
450 if [[ 'foo()' == '*()' ]]; then echo match3; fi
451
452 ## STDOUT:
453 match1
454 match2
455 match1
456 match2
457 ## END
458
459 #### negative numbers - zero, decimal, octal, hex, base N
460
461 [[ -0 -eq 0 ]]; echo zero=$?
462
463 [[ -42 -eq -42 ]]; echo decimal=$?
464
465 # note: mksh doesn't do octal conversion
466 [[ -0123 -eq -83 ]]; echo octal=$?
467
468 [[ -0xff -eq -255 ]]; echo hex=$?
469
470 [[ -64#a -eq -10 ]]; echo baseN=$?
471
472 ## STDOUT:
473 zero=0
474 decimal=0
475 octal=0
476 hex=0
477 baseN=0
478 ## END
479
480 ## BUG mksh STDOUT:
481 zero=0
482 decimal=0
483 octal=1
484 hex=2
485 baseN=2
486 ## END