OILS / spec / ysh-expr-compare.test.sh View on Github | oils.pub

429 lines, 266 significant
1## oils_failures_allowed: 1
2
3#### Exact equality with === and !==
4shopt -s ysh:all
5
6if (3 === 3) {
7 echo 'ok'
8}
9if (3 === '3') {
10 echo 'FAIL'
11}
12
13if (3 !== 3) {
14 echo 'FAIL'
15}
16if (3 !== '3') {
17 echo 'ok'
18}
19
20# dicts
21var d1 = {'a': 1, 'b': 2}
22var d2 = {'a': 1, 'b': 2}
23var d3 = {'a': 1, 'b': 3}
24if (d1 === d2) {
25 echo 'ok'
26}
27if (d1 === d3) {
28 echo 'FAIL'
29}
30if (d1 !== d3) {
31 echo 'ok'
32}
33
34## STDOUT:
35ok
36ok
37ok
38ok
39## END
40
41#### Approximate equality of Str x {Str, Int, Bool} with ~==
42shopt -s ysh:all
43
44# Note: for now there's no !~== operator. Use: not (a ~== b)
45
46if (' foo ' ~== 'foo') {
47 echo Str-Str
48}
49if (' BAD ' ~== 'foo') {
50 echo FAIL
51}
52
53if ('3 ' ~== 3) {
54 echo Str-Int
55}
56
57if ('-3 ' ~== -3) {
58 echo Str-Negative
59}
60
61if ('-3_456' ~== -3456) {
62 echo Str-Underscore
63}
64
65if ('4 ' ~== '3') {
66 echo FAIL
67}
68
69if (' true ' ~== true) {
70 echo Str-Bool
71}
72if (' true ' ~== false) {
73 echo FAIL
74}
75
76const matrix = [
77 ' TRue ' ~== true, # case insentiive
78 ' FALse ' ~== false,
79]
80
81# = matrix
82if (matrix === [true, true]) {
83 echo 'bool matrix'
84}
85
86## STDOUT:
87Str-Str
88Str-Int
89Str-Negative
90Str-Underscore
91Str-Bool
92bool matrix
93## END
94
95#### Wrong Types with ~==
96shopt -s ysh:all
97
98# The LHS side should be a string
99
100echo one
101if (['1'] ~== ['1']) {
102 echo bad
103}
104echo two
105
106if (3 ~== 3) {
107 echo bad
108}
109
110## status: 1
111## STDOUT:
112one
113## END
114
115#### === on float not allowed
116
117$SH -c '
118shopt -s ysh:upgrade
119pp test_ (1.0 === 2.0)
120echo ok
121'
122echo status=$?
123
124$SH -c '
125shopt -s ysh:upgrade
126pp test_ (42 === 3.0)
127echo ok
128'
129echo status=$?
130
131## STDOUT:
132status=3
133status=3
134## END
135
136
137#### floatsEqual()
138
139var x = 42.0
140pp test_ (floatsEqual(42.0, x))
141
142pp test_ (floatsEqual(42.0, x + 1))
143
144## STDOUT:
145(Bool) true
146(Bool) false
147## END
148
149#### Comparison converts from Str -> Int or Float
150shopt --set parse_ysh_expr_sub
151
152echo ' i i' $[1 < 2]
153echo 'si i' $['1' < 2]
154echo ' i si' $[1 < '2']
155echo ---
156
157echo ' f f' $[2.5 > 1.5]
158echo 'sf f' $['2.5' > 1.5]
159echo ' f sf' $[2.5 > '1.5']
160echo ---
161
162echo ' i f' $[4 <= 1.5]
163echo 'si f' $['4' <= 1.5]
164echo ' i sf' $[4 <= '1.5']
165echo ---
166
167echo ' f i' $[5.0 >= 2]
168echo 'sf i' $['5.0' >= 2]
169echo ' f si' $[5.0 >= '2']
170
171## STDOUT:
172 i i true
173si i true
174 i si true
175---
176 f f true
177sf f true
178 f sf true
179---
180 i f false
181si f false
182 i sf false
183---
184 f i true
185sf i true
186 f si true
187## END
188
189#### Comparison of Int
190shopt -s ysh:upgrade
191
192if (1 < 2) {
193 echo '<'
194}
195if (2 <= 2) {
196 echo '<='
197}
198if (5 > 4) {
199 echo '>'
200}
201if (5 >= 5) {
202 echo '>='
203}
204
205if (2 < 1) {
206 echo no
207}
208
209## STDOUT:
210<
211<=
212>
213>=
214## END
215
216#### Comparison of Str does conversion to Int
217shopt -s ysh:upgrade
218
219if ('2' < '11') {
220 echo '<'
221}
222if ('2' <= '2') {
223 echo '<='
224}
225if ('11' > '2') {
226 echo '>'
227}
228if ('5' >= '5') {
229 echo '>='
230}
231
232if ('2' < '1') {
233 echo no
234}
235
236## STDOUT:
237<
238<=
239>
240>=
241## END
242
243
244#### Mixed Type Comparison does conversion to Int
245shopt -s ysh:upgrade
246
247if (2 < '11') {
248 echo '<'
249}
250if (2 <= '2') {
251 echo '<='
252}
253if (11 > '2') {
254 echo '>'
255}
256if (5 >= '5') {
257 echo '>='
258}
259
260if (2 < '1') {
261 echo no
262}
263
264## STDOUT:
265<
266<=
267>
268>=
269## END
270
271
272#### Invalid String is an error
273shopt -s ysh:upgrade
274
275try {
276 = '3' < 'bar'
277}
278echo code=$[_error.code]
279
280try {
281 = '3' < '123_4'
282}
283echo code=$[_error.code]
284
285## status: 3
286## STDOUT:
287## END
288
289
290#### Bool conversion -- explicit allowed, implicit not allowed
291
292shopt -s ysh:upgrade
293
294if (int(false) < int(true)) {
295 echo '<'
296}
297
298if (int(false) <= int(false) ) {
299 echo '<='
300}
301
302# JavaScript and Python both have this, but YSH prefers being explicit
303
304if (true < false) {
305 echo 'BAD'
306}
307echo 'should not get here'
308
309## status: 3
310## STDOUT:
311<
312<=
313## END
314
315
316#### Chained Comparisons
317shopt -s ysh:upgrade
318
319if (1 < 2 < 3) {
320 echo '123'
321}
322if (1 < 2 <= 2 <= 3 < 4) {
323 echo '123'
324}
325
326if (1 < 2 < 2) {
327 echo '123'
328} else {
329 echo 'no'
330}
331## STDOUT:
332123
333123
334no
335## END
336
337#### List / "Tuple" comparison is not allowed
338
339shopt -s ysh:upgrade
340
341var t1 = 3, 0
342var t2 = 4, 0
343var t3 = 3, 1
344
345if (t2 > t1) { echo yes1 }
346if (t3 > t1) { echo yes2 }
347if ( (0,0) > t1) { echo yes3 }
348
349## status: 3
350## STDOUT:
351## END
352
353#### Ternary op behaves like if statement
354shopt -s ysh:upgrade
355
356if ([1]) {
357 var y = 42
358} else {
359 var y = 0
360}
361echo y=$y
362
363var x = 42 if [1] else 0
364echo x=$x
365
366## STDOUT:
367y=42
368x=42
369## END
370
371#### Undefined comparisons
372shopt -s ysh:all
373
374func f() { true }
375var mydict = {}
376var myexpr = ^[123]
377
378var unimpl = [
379 / [a-z]+ /, # Eggex
380 myexpr, # Expr
381 ^(echo hello), # Block
382 f, # Func
383 ''.upper, # BoundFunc
384 # These cannot be constructed
385 # - Proc
386 # - Slice
387 # - Range
388]
389
390for val in (unimpl) {
391 try { = val === val }
392 if (_status !== 3) {
393 exit 1
394 }
395}
396## STDOUT:
397## END
398
399#### Non-comparable types in case arms
400var myexpr = ^[123]
401
402case (myexpr) {
403 (myexpr) { echo 123; }
404}
405## status: 3
406## STDOUT:
407## END
408
409#### object identity
410
411var d = {}
412var s = 'str'
413
414pp test_ (d is d)
415pp test_ (d is not {})
416echo
417
418pp test_ (d is s)
419pp test_ (d is not s)
420
421## STDOUT:
422(Bool) true
423(Bool) true
424
425(Bool) false
426(Bool) true
427## END
428
429