1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3;
18
19 import org.apache.commons.jexl3.junit.Asserter;
20 import org.junit.Assert;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.w3c.dom.Attr;
24 import org.w3c.dom.Document;
25 import org.w3c.dom.NamedNodeMap;
26 import org.w3c.dom.Node;
27
28 import javax.xml.parsers.DocumentBuilder;
29 import javax.xml.parsers.DocumentBuilderFactory;
30 import java.io.ByteArrayInputStream;
31 import java.io.InputStream;
32 import java.math.BigDecimal;
33 import java.math.BigInteger;
34 import java.math.MathContext;
35 import java.nio.charset.StandardCharsets;
36 import java.util.Arrays;
37 import java.util.Date;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.concurrent.atomic.AtomicBoolean;
42
43 @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
44 public class ArithmeticTest extends JexlTestCase {
45
46 private static final double EPSILON = 1.e-6;
47 private final Asserter asserter;
48 private final JexlArithmetic jexla;
49 private final JexlArithmetic jexlb;
50 private final Date date = new Date();
51
52 public ArithmeticTest() {
53 super("ArithmeticTest");
54 asserter = new Asserter(JEXL);
55 jexla = JEXL.getArithmetic();
56 JexlOptions options = new JexlOptions();
57 options.setStrictArithmetic(false);
58 jexlb = jexla.options(options);
59 }
60
61 @Before
62 @Override
63 public void setUp() {
64 }
65
66 static private void assertNullOperand(java.util.function.Supplier<Object> fun) {
67 try {
68 Assert.assertNull(fun.get());
69 } catch(JexlArithmetic.NullOperand xany) {
70 Assert.assertNotNull(xany);
71 }
72 }
73
74 static private void assertArithmeticException(java.util.function.Supplier<Object> fun) {
75 try {
76 Assert.assertNull(fun.get());
77 } catch(ArithmeticException xany) {
78 Assert.assertNotNull(xany);
79 }
80 }
81
82 @Test
83 public void testModEdge() {
84 assertNullOperand(() -> jexla.mod(null, null));
85 Assert.assertEquals(0, jexlb.mod(null, null));
86 assertArithmeticException(() -> jexla.mod(1, 0));
87 assertArithmeticException(() -> jexla.mod(1L, 0L));
88 assertArithmeticException(() -> jexla.mod(1f, 0f));
89 assertArithmeticException(() -> jexla.mod(1d, 0d));
90 assertArithmeticException(() -> jexla.mod(BigInteger.ONE, BigInteger.ZERO));
91 assertArithmeticException(() -> jexla.mod(BigInteger.ONE, BigDecimal.ZERO));
92 assertNullOperand(()-> jexla.divide(null, null));
93 }
94
95 @Test
96 public void testUnaryopsEdges() {
97 assertArithmeticException(()-> jexla.positivize(date) );
98 assertNullOperand(()-> jexla.positivize(null));
99 Assert.assertNull(jexlb.positivize(null));
100 Assert.assertEquals(42, jexla.positivize((char) 42));
101 Assert.assertEquals(Boolean.TRUE, jexla.positivize(Boolean.TRUE));
102 Assert.assertEquals(Boolean.FALSE, jexla.positivize(Boolean.FALSE));
103 Assert.assertEquals(Boolean.TRUE, jexla.positivize(new AtomicBoolean(true)));
104 Assert.assertEquals(Boolean.FALSE, jexla.positivize(new AtomicBoolean(false)));
105
106 assertNullOperand(()-> jexla.negate(null));
107 Assert.assertNull(jexlb.negate(null));
108 assertArithmeticException(()-> jexla.negate(date));
109 Assert.assertEquals(Boolean.FALSE, jexla.negate(Boolean.TRUE));
110 Assert.assertEquals(Boolean.TRUE, jexla.negate(Boolean.FALSE));
111 }
112
113 @Test
114 public void testDivideEdges() {
115 assertNullOperand(()-> jexla.divide(null, null));
116 Assert.assertEquals(0, jexlb.divide(null, null));
117 assertNullOperand(() -> jexla.divide(null, null));
118 Assert.assertEquals(0, jexlb.mod(null, null));
119 assertArithmeticException(() -> jexla.divide(1, 0));
120 assertArithmeticException(() -> jexla.divide(1L, 0L));
121 assertArithmeticException(() -> jexla.divide(1f, 0f));
122 assertArithmeticException(() -> jexla.divide(1d, 0d));
123 assertArithmeticException(() -> jexla.divide(BigInteger.ONE, BigInteger.ZERO));
124 assertArithmeticException(() -> jexla.divide(BigInteger.ONE, BigDecimal.ZERO));
125 }
126
127
128 @Test
129 public void testOperatorsEdges() {
130 assertNullOperand(()-> jexla.multiply(null, null));
131 Assert.assertEquals(0, jexlb.multiply(null, null));
132 assertNullOperand(()-> jexla.add(null, null));
133 Assert.assertEquals(0, jexlb.add(null, null));
134 assertNullOperand(()-> jexla.subtract(null, null));
135 Assert.assertEquals(0, jexlb.subtract(null, null));
136
137 Assert.assertTrue(jexla.contains(null, null));
138 Assert.assertFalse(jexla.contains(true, null));
139 Assert.assertFalse(jexla.contains(null, true));
140 Assert.assertTrue(jexla.endsWith(null, null));
141 Assert.assertFalse(jexla.endsWith(true, null));
142 Assert.assertFalse(jexla.endsWith(null, true));
143 Assert.assertTrue(jexla.startsWith(null, null));
144 Assert.assertFalse(jexla.startsWith(true, null));
145 Assert.assertFalse(jexla.startsWith(null, true));
146 Assert.assertTrue(jexla.isEmpty(null));
147 }
148
149 @Test
150 public void testIntegerCoercionEdges() {
151 assertNullOperand(()-> jexla.toBoolean(null));
152 Assert.assertTrue(jexla.toBoolean(date));
153
154 assertNullOperand(()-> jexla.toInteger(null));
155 Assert.assertEquals(0, jexlb.toInteger(null));
156 assertArithmeticException(()-> jexla.toInteger(date));
157 Assert.assertEquals(0, jexla.toInteger(Double.NaN));
158 Assert.assertEquals(0, jexla.toInteger(""));
159 Assert.assertEquals((int) 'b', jexla.toInteger('b'));
160 Assert.assertEquals(1, jexla.toInteger(new AtomicBoolean(true)));
161 Assert.assertEquals(0, jexla.toInteger(new AtomicBoolean(false)));
162
163
164 assertNullOperand(()-> jexla.toLong(null));
165 Assert.assertEquals(0L, jexlb.toLong(null));
166 assertArithmeticException(()-> jexla.toLong(date));
167 Assert.assertEquals(0L, jexla.toLong(Double.NaN));
168 Assert.assertEquals(0L, jexla.toLong(""));
169 Assert.assertEquals('b', jexla.toLong('b'));
170 Assert.assertEquals(1L, jexla.toLong(new AtomicBoolean(true)));
171 Assert.assertEquals(0L, jexla.toLong(new AtomicBoolean(false)));
172 }
173
174 @Test
175 public void testRealCoercionEdges() {
176 assertNullOperand(()-> jexla.toDouble(null));
177 Assert.assertEquals(0.0d, jexlb.toDouble(null), EPSILON);
178 Assert.assertEquals(32.0d, jexlb.toDouble((char) 32), EPSILON);
179 assertArithmeticException(()-> jexla.toDouble(date));
180 Assert.assertTrue(Double.isNaN(jexla.toDouble("")));
181 Assert.assertEquals("", jexla.toString(Double.NaN));
182
183 assertNullOperand(()-> jexla.toBigInteger(null));
184 assertArithmeticException(()-> jexla.toBigInteger(date));
185 Assert.assertEquals(BigInteger.ZERO, jexla.toBigInteger(Double.NaN));
186 Assert.assertEquals(BigInteger.ZERO, jexla.toBigInteger(""));
187 Assert.assertEquals(BigInteger.ZERO, jexla.toBigInteger((char) 0));
188
189 assertNullOperand(()-> jexla.toBigDecimal(null));
190 assertArithmeticException(()-> jexla.toBigDecimal(date));
191
192 Assert.assertEquals(BigDecimal.ZERO, jexla.toBigDecimal(Double.NaN));
193 Assert.assertEquals(BigDecimal.ZERO, jexla.toBigDecimal(""));
194 Assert.assertEquals(BigDecimal.ZERO, jexla.toBigDecimal((char) 0));
195 }
196
197 @Test
198 public void testUndefinedVar() throws Exception {
199 asserter.failExpression("objects[1].status", ".*variable 'objects' is undefined.*");
200 }
201
202 @Test
203 public void testLeftNullOperand() throws Exception {
204 asserter.setVariable("left", null);
205 asserter.setVariable("right", Integer.valueOf(8));
206 asserter.setStrict(true);
207 asserter.failExpression("left + right", ".*null.*");
208 asserter.failExpression("left - right", ".*null.*");
209 asserter.failExpression("left * right", ".*null.*");
210 asserter.failExpression("left / right", ".*null.*");
211 asserter.failExpression("left % right", ".*null.*");
212 asserter.failExpression("left & right", ".*null.*");
213 asserter.failExpression("left | right", ".*null.*");
214 asserter.failExpression("left ^ right", ".*null.*");
215 asserter.failExpression("left < right", ".*null.*");
216 asserter.failExpression("left <= right", ".*null.*");
217 asserter.failExpression("left > right", ".*null.*");
218 asserter.failExpression("left >= right", ".*null.*");
219 }
220
221 @Test
222 public void testLeftNullOperand2() throws Exception {
223 asserter.setVariable("x.left", null);
224 asserter.setVariable("right", Integer.valueOf(8));
225 asserter.setStrict(true);
226 asserter.failExpression("x.left + right", ".*null.*");
227 asserter.failExpression("x.left - right", ".*null.*");
228 asserter.failExpression("x.left * right", ".*null.*");
229 asserter.failExpression("x.left / right", ".*null.*");
230 asserter.failExpression("x.left % right", ".*null.*");
231 asserter.failExpression("x.left & right", ".*null.*");
232 asserter.failExpression("x.left | right", ".*null.*");
233 asserter.failExpression("x.left ^ right", ".*null.*");
234 asserter.failExpression("x.left < right", ".*null.*");
235 asserter.failExpression("x.left <= right", ".*null.*");
236 asserter.failExpression("x.left > right", ".*null.*");
237 asserter.failExpression("x.left >= right", ".*null.*");
238 }
239
240 @Test
241 public void testRightNullOperand() throws Exception {
242 asserter.setVariable("left", Integer.valueOf(9));
243 asserter.setVariable("right", null);
244 asserter.failExpression("left + right", ".*null.*");
245 asserter.failExpression("left - right", ".*null.*");
246 asserter.failExpression("left * right", ".*null.*");
247 asserter.failExpression("left / right", ".*null.*");
248 asserter.failExpression("left % right", ".*null.*");
249 asserter.failExpression("left & right", ".*null.*");
250 asserter.failExpression("left | right", ".*null.*");
251 asserter.failExpression("left ^ right", ".*null.*");
252 asserter.failExpression("left < right", ".*null.*");
253 asserter.failExpression("left <= right", ".*null.*");
254 asserter.failExpression("left > right", ".*null.*");
255 asserter.failExpression("left >= right", ".*null.*");
256 }
257
258 @Test
259 public void testRightNullOperand2() throws Exception {
260 asserter.setVariable("left", Integer.valueOf(9));
261 asserter.setVariable("y.right", null);
262 asserter.failExpression("left + y.right", ".*null.*");
263 asserter.failExpression("left - y.right", ".*null.*");
264 asserter.failExpression("left * y.right", ".*null.*");
265 asserter.failExpression("left / y.right", ".*null.*");
266 asserter.failExpression("left % y.right", ".*null.*");
267 asserter.failExpression("left & y.right", ".*null.*");
268 asserter.failExpression("left | y.right", ".*null.*");
269 asserter.failExpression("left ^ y.right", ".*null.*");
270 asserter.failExpression("left < y.right", ".*null.*");
271 asserter.failExpression("left <= y.right", ".*null.*");
272 asserter.failExpression("left > y.right", ".*null.*");
273 asserter.failExpression("left >= y.right", ".*null.*");
274 }
275
276 @Test
277 public void testNullOperands() throws Exception {
278 asserter.setVariable("left", null);
279 asserter.setVariable("right", null);
280 asserter.failExpression("left + right", ".*null.*");
281 asserter.failExpression("left - right", ".*null.*");
282 asserter.failExpression("left * right", ".*null.*");
283 asserter.failExpression("left / right", ".*null.*");
284 asserter.failExpression("left % right", ".*null.*");
285 asserter.failExpression("left & right", ".*null.*");
286 asserter.failExpression("left | right", ".*null.*");
287 asserter.failExpression("left ^ right", ".*null.*");
288 }
289
290 @Test
291 public void testNullOperand() throws Exception {
292 asserter.setVariable("right", null);
293 asserter.failExpression("~right", ".*null.*");
294 }
295
296 @Test
297 public void testBigDecimal() throws Exception {
298 asserter.setVariable("left", new BigDecimal(2));
299 asserter.setVariable("right", new BigDecimal(6));
300 asserter.assertExpression("left + right", new BigDecimal(8));
301 asserter.assertExpression("right - left", new BigDecimal(4));
302 asserter.assertExpression("right * left", new BigDecimal(12));
303 asserter.assertExpression("right / left", new BigDecimal(3));
304 asserter.assertExpression("right % left", new BigDecimal(0));
305 }
306
307 @Test
308 public void testBigInteger() throws Exception {
309 asserter.setVariable("left", new BigInteger("2"));
310 asserter.setVariable("right", new BigInteger("6"));
311 asserter.assertExpression("left + right", new BigInteger("8"));
312 asserter.assertExpression("right - left", new BigInteger("4"));
313 asserter.assertExpression("right * left", new BigInteger("12"));
314 asserter.assertExpression("right / left", new BigInteger("3"));
315 asserter.assertExpression("right % left", new BigInteger("0"));
316 }
317
318 @Test
319 public void testOverflows() throws Exception {
320 asserter.assertExpression("1 + 2147483647", Long.valueOf("2147483648"));
321 asserter.assertExpression("3 + " + (Long.MAX_VALUE - 2), BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE));
322 asserter.assertExpression("-2147483648 - 1", Long.valueOf("-2147483649"));
323 asserter.assertExpression("-3 + " + (Long.MIN_VALUE + 2), BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE));
324 asserter.assertExpression("1 + 9223372036854775807", new BigInteger("9223372036854775808"));
325 asserter.assertExpression("-1 + (-9223372036854775808)", new BigInteger("-9223372036854775809"));
326 asserter.assertExpression("-9223372036854775808 - 1", new BigInteger("-9223372036854775809"));
327 final BigInteger maxl = BigInteger.valueOf(Long.MAX_VALUE);
328 asserter.assertExpression(maxl + " * " + maxl , maxl.multiply(maxl));
329 }
330
331
332
333
334 @Test
335 public void testUnaryMinus() throws Exception {
336 asserter.setVariable("aByte", new Byte((byte) 1));
337 asserter.setVariable("aShort", new Short((short) 2));
338 asserter.setVariable("anInteger", new Integer(3));
339 asserter.setVariable("aLong", new Long(4));
340 asserter.setVariable("aFloat", new Float(5.5));
341 asserter.setVariable("aDouble", new Double(6.6));
342 asserter.setVariable("aBigInteger", new BigInteger("7"));
343 asserter.setVariable("aBigDecimal", new BigDecimal("8.8"));
344
345
346 for(int i = 0 ; i < 2; ++i) {
347 asserter.assertExpression("-3", new Integer("-3"));
348 asserter.assertExpression("-3.0", new Double("-3.0"));
349 asserter.assertExpression("-aByte", new Byte((byte) -1));
350 asserter.assertExpression("-aShort", new Short((short) -2));
351 asserter.assertExpression("-anInteger", new Integer(-3));
352 asserter.assertExpression("-aLong", new Long(-4));
353 asserter.assertExpression("-aFloat", new Float(-5.5));
354 asserter.assertExpression("-aDouble", new Double(-6.6));
355 asserter.assertExpression("-aBigInteger", new BigInteger("-7"));
356 asserter.assertExpression("-aBigDecimal", new BigDecimal("-8.8"));
357 }
358 }
359
360
361
362
363 @Test
364 public void testUnaryPlus() throws Exception {
365 asserter.setVariable("aByte", new Byte((byte) 1));
366 asserter.setVariable("aShort", new Short((short) 2));
367 asserter.setVariable("anInteger", new Integer(3));
368 asserter.setVariable("aLong", new Long(4));
369 asserter.setVariable("aFloat", new Float(5.5));
370 asserter.setVariable("aDouble", new Double(6.6));
371 asserter.setVariable("aBigInteger", new BigInteger("7"));
372 asserter.setVariable("aBigDecimal", new BigDecimal("8.8"));
373
374
375 for(int i = 0 ; i < 2; ++i) {
376 asserter.assertExpression("+3", new Integer("3"));
377 asserter.assertExpression("+3.0", new Double("3.0"));
378 asserter.assertExpression("+aByte", new Integer(1));
379 asserter.assertExpression("+aShort", new Integer(2));
380 asserter.assertExpression("+anInteger", new Integer(3));
381 asserter.assertExpression("+aLong", new Long(4));
382 asserter.assertExpression("+aFloat", new Float(5.5));
383 asserter.assertExpression("+aDouble", new Double(6.6));
384 asserter.assertExpression("+aBigInteger", new BigInteger("7"));
385 asserter.assertExpression("+aBigDecimal", new BigDecimal("8.8"));
386 }
387 }
388
389 @Test
390 public void testMinusMinusPrefix() throws Exception {
391 asserter.setVariable("aByte", new Byte((byte) 2));
392 asserter.setVariable("aShort", new Short((short) 3));
393 asserter.setVariable("anInteger", new Integer(4));
394 asserter.setVariable("aLong", new Long(5));
395 asserter.setVariable("aFloat", new Float(6.6));
396 asserter.setVariable("aDouble", new Double(7.7));
397 asserter.setVariable("aBigInteger", new BigInteger("8"));
398 asserter.setVariable("aBigDecimal", new BigDecimal("9.9"));
399 asserter.setVariable("aString", "forty-two");
400
401 asserter.assertExpression("--aByte", new Byte((byte) 1));
402 asserter.assertExpression("--aShort", new Short((short) 2));
403 asserter.assertExpression("--anInteger", new Integer(3));
404 asserter.assertExpression("--aLong", new Long(4));
405 asserter.assertExpression("--aFloat", new Float(5.6));
406 asserter.assertExpression("--aDouble", new Double(6.7));
407 asserter.assertExpression("--aBigInteger", new BigInteger("7"));
408 asserter.assertExpression("--aBigDecimal", new BigDecimal("8.9"));
409
410 asserter.failExpression("aString--", "--", String::contains);
411 }
412
413 @Test
414 public void testMinusMinusPostfix() throws Exception {
415 asserter.setVariable("aByte", new Byte((byte) 2));
416 asserter.setVariable("aShort", new Short((short) 3));
417 asserter.setVariable("anInteger", new Integer(4));
418 asserter.setVariable("aLong", new Long(5));
419 asserter.setVariable("aFloat", new Float(6.6));
420 asserter.setVariable("aDouble", new Double(7.7));
421 asserter.setVariable("aBigInteger", new BigInteger("8"));
422 asserter.setVariable("aBigDecimal", new BigDecimal("9.9"));
423 asserter.setVariable("aString", "forty-two");
424
425 asserter.assertExpression("aByte--",new Byte((byte) 2));
426 asserter.assertExpression("aShort--", new Short((short) 3));
427 asserter.assertExpression("anInteger--", new Integer(4));
428 asserter.assertExpression("aLong--", new Long(5));
429 asserter.assertExpression("aFloat--", new Float(6.6));
430 asserter.assertExpression("aDouble--", new Double(7.7));
431 asserter.assertExpression("aBigInteger--", new BigInteger("8"));
432 asserter.assertExpression("aBigDecimal--", new BigDecimal("9.9"));
433
434 asserter.assertExpression("aByte", new Byte((byte) 1));
435 asserter.assertExpression("aShort", new Short((short) 2));
436 asserter.assertExpression("anInteger", new Integer(3));
437 asserter.assertExpression("aLong", new Long(4));
438 asserter.assertExpression("aFloat", new Float(5.6));
439 asserter.assertExpression("aDouble", new Double(6.7));
440 asserter.assertExpression("aBigInteger", new BigInteger("7"));
441 asserter.assertExpression("aBigDecimal", new BigDecimal("8.9"));
442
443 asserter.failExpression("aString--", "--", String::contains);
444 }
445
446 @Test
447 public void testPlusPlusPrefix() throws Exception {
448 asserter.setVariable("aByte", new Byte((byte) 0));
449 asserter.setVariable("aShort", new Short((short) 1));
450 asserter.setVariable("anInteger", new Integer(2));
451 asserter.setVariable("aLong", new Long(3));
452 asserter.setVariable("aFloat", new Float(4.4));
453 asserter.setVariable("aDouble", new Double(5.5));
454 asserter.setVariable("aBigInteger", new BigInteger("6"));
455 asserter.setVariable("aBigDecimal", new BigDecimal("7.7"));
456 asserter.setVariable("aString", "forty-two");
457
458 asserter.assertExpression("++aByte", new Byte((byte) 1));
459 asserter.assertExpression("++aShort", new Short((short) 2));
460 asserter.assertExpression("++anInteger", new Integer(3));
461 asserter.assertExpression("++aLong", new Long(4));
462 asserter.assertExpression("++aFloat", new Float(5.4));
463 asserter.assertExpression("++aDouble", new Double(6.5));
464 asserter.assertExpression("++aBigInteger", new BigInteger("7"));
465 asserter.assertExpression("++aBigDecimal", new BigDecimal("8.7"));
466
467 asserter.failExpression("++aString", "++", String::contains);
468 }
469
470 @Test
471 public void testPlusPlusPostfix() throws Exception {
472 asserter.setVariable("aByte", new Byte((byte) 0));
473 asserter.setVariable("aShort", new Short((short) 1));
474 asserter.setVariable("anInteger", new Integer(2));
475 asserter.setVariable("aLong", new Long(3));
476 asserter.setVariable("aFloat", new Float(4.4));
477 asserter.setVariable("aDouble", new Double(5.5));
478 asserter.setVariable("aBigInteger", new BigInteger("6"));
479 asserter.setVariable("aBigDecimal", new BigDecimal("7.7"));
480 asserter.setVariable("aString", "forty-two");
481
482 asserter.assertExpression("aByte++", new Byte((byte) 0));
483 asserter.assertExpression("aShort++", new Short((short) 1));
484 asserter.assertExpression("anInteger++", new Integer(2));
485 asserter.assertExpression("aLong++", new Long(3));
486 asserter.assertExpression("aFloat++", new Float(4.4));
487 asserter.assertExpression("aDouble++", new Double(5.5));
488 asserter.assertExpression("aBigInteger++", new BigInteger("6"));
489 asserter.assertExpression("aBigDecimal++", new BigDecimal("7.7"));
490
491 asserter.assertExpression("aByte", new Byte((byte) 1));
492 asserter.assertExpression("aShort", new Short((short) 2));
493 asserter.assertExpression("anInteger", new Integer(3));
494 asserter.assertExpression("aLong", new Long(4));
495 asserter.assertExpression("aFloat", new Float(5.4));
496 asserter.assertExpression("aDouble", new Double(6.5));
497 asserter.assertExpression("aBigInteger", new BigInteger("7"));
498 asserter.assertExpression("aBigDecimal", new BigDecimal("8.7"));
499
500 asserter.failExpression("aString++", "++", String::contains);
501 }
502
503 @Test
504 public void testNarrowBig() throws Exception {
505 List<String> ls = Arrays.asList("zero", "one", "two");
506 asserter.setVariable("list",ls);
507 asserter.setVariable("aBigDecimal", new BigDecimal("1"));
508 asserter.setVariable("aBigInteger", new BigDecimal("1"));
509 asserter.assertExpression("list.get(aBigDecimal)", "one");
510 asserter.assertExpression("list.get(aBigInteger)", "one");
511 }
512
513 @Test
514 public void testNarrowBigDecimal() throws Exception {
515 asserter.setVariable("bi420", BigInteger.valueOf(420));
516 asserter.setVariable("bi10", BigInteger.valueOf(10));
517 asserter.setVariable("bd420", new BigDecimal("420"));
518 asserter.setVariable("bd10", new BigDecimal("10"));
519 asserter.assertExpression("420 / bi10", 42);
520 asserter.assertExpression("420l / bi10", 42L);
521 asserter.assertExpression("bi420 / 420", 1);
522 asserter.assertExpression("bi420 / 420l", 1L);
523 asserter.assertExpression("bd420 / 10", new BigDecimal("42"));
524 }
525
526
527
528
529 @Test
530 public void testCalculations() throws Exception {
531 asserter.setStrict(true, false);
532
533
534
535 asserter.setVariable("imanull", null);
536 asserter.assertExpression("imanull + 2", new Integer(2));
537 asserter.assertExpression("imanull + imanull", new Integer(0));
538 asserter.setVariable("foo", new Integer(2));
539
540 asserter.assertExpression("foo + 2", new Integer(4));
541 asserter.assertExpression("3 + 3", new Integer(6));
542 asserter.assertExpression("3 + 3 + foo", new Integer(8));
543 asserter.assertExpression("3 * 3", new Integer(9));
544 asserter.assertExpression("3 * 3 + foo", new Integer(11));
545 asserter.assertExpression("3 * 3 - foo", new Integer(7));
546
547
548
549
550 asserter.assertExpression("(4 + 3) * 6", new Integer(42));
551 asserter.assertExpression("(8 - 2) * 7", new Integer(42));
552
553
554
555
556 asserter.assertExpression("3 * \"3.0\"", new Double(9));
557 asserter.assertExpression("3 * 3.0", new Double(9));
558
559
560
561
562 asserter.setStrict(false, false);
563 asserter.assertExpression("6 / 3", new Integer(6 / 3));
564 asserter.assertExpression("6.4 / 3", new Double(6.4 / 3));
565 asserter.assertExpression("0 / 3", new Integer(0 / 3));
566 asserter.assertExpression("3 / 0", new Double(0));
567 asserter.assertExpression("4 % 3", new Integer(1));
568 asserter.assertExpression("4.8 % 3", new Double(4.8 % 3));
569
570 }
571
572 @Test
573 public void testCoercions() throws Exception {
574 asserter.assertExpression("1", new Integer(1));
575 asserter.assertExpression("5L", new Long(5));
576
577 asserter.setVariable("I2", new Integer(2));
578 asserter.setVariable("L2", new Long(2));
579 asserter.setVariable("L3", new Long(3));
580 asserter.setVariable("B10", BigInteger.TEN);
581
582
583 asserter.assertExpression("I2 + 2", new Integer(4));
584 asserter.assertExpression("I2 * 2", new Integer(4));
585 asserter.assertExpression("I2 - 2", new Integer(0));
586 asserter.assertExpression("I2 / 2", new Integer(1));
587
588
589 asserter.assertExpression("I2 * L2", new Long(4));
590 asserter.assertExpression("I2 / L2", new Long(1));
591
592
593 asserter.assertExpression("L2 + 3", new Long(5));
594 asserter.assertExpression("L2 + L3", new Long(5));
595 asserter.assertExpression("L2 / L2", new Long(1));
596 asserter.assertExpression("L2 / 2", new Long(1));
597
598
599 asserter.assertExpression("B10 / 10", BigInteger.ONE);
600 asserter.assertExpression("B10 / I2", new BigInteger("5"));
601 asserter.assertExpression("B10 / L2", new BigInteger("5"));
602 }
603
604
605 @Test
606 public void testLongLiterals() {
607 final JexlEvalContext ctxt = new JexlEvalContext();
608 final JexlOptions options = ctxt.getEngineOptions();
609 options.setStrictArithmetic(true);
610 final String stmt = "{a = 10L; b = 10l; c = 42.0D; d = 42.0d; e=56.3F; f=56.3f; g=63.5; h=0x10; i=010; j=0x10L; k=010l}";
611 final JexlScript expr = JEXL.createScript(stmt);
612 expr.execute(ctxt);
613 Assert.assertEquals(10L, ctxt.get("a"));
614 Assert.assertEquals(10L, ctxt.get("b"));
615 Assert.assertEquals(42.0D, ctxt.get("c"));
616 Assert.assertEquals(42.0d, ctxt.get("d"));
617 Assert.assertEquals(56.3f, ctxt.get("e"));
618 Assert.assertEquals(56.3f, ctxt.get("f"));
619 Assert.assertEquals(63.5d, ctxt.get("g"));
620 Assert.assertEquals(0x10, ctxt.get("h"));
621 Assert.assertEquals(010, ctxt.get("i"));
622 Assert.assertEquals(0x10L, ctxt.get("j"));
623 Assert.assertEquals(010L, ctxt.get("k"));
624 }
625
626 @Test
627 public void testBigLiteralValue() {
628 final JexlEvalContext ctxt = new JexlEvalContext();
629 final JexlOptions options = ctxt.getEngineOptions();
630 options.setStrictArithmetic(true);
631 final JexlExpression e = JEXL.createExpression("9223372036854775806.5B");
632 final String res = String.valueOf(e.evaluate(ctxt));
633 Assert.assertEquals("9223372036854775806.5", res);
634 }
635
636 @Test
637 public void testBigdOp() {
638 final BigDecimal sevendot475 = new BigDecimal("7.475");
639 final BigDecimal SO = new BigDecimal("325");
640 final JexlContext jc = new MapContext();
641 jc.set("SO", SO);
642
643 final String expr = "2.3*SO/100";
644
645 final Object evaluate = JEXL.createExpression(expr).evaluate(jc);
646 Assert.assertEquals(sevendot475, evaluate);
647 }
648
649
650 @Test
651 public void testBigLiterals() {
652 final JexlEvalContext ctxt = new JexlEvalContext();
653 final JexlOptions options = ctxt.getEngineOptions();
654 options.setStrictArithmetic(true);
655 final String stmt = "{a = 10H; b = 10h; c = 42.0B; d = 42.0b;}";
656 final JexlScript expr = JEXL.createScript(stmt);
657 expr.execute(ctxt);
658 Assert.assertEquals(new BigInteger("10"), ctxt.get("a"));
659 Assert.assertEquals(new BigInteger("10"), ctxt.get("b"));
660 Assert.assertEquals(new BigDecimal("42.0"), ctxt.get("c"));
661 Assert.assertEquals(new BigDecimal("42.0"), ctxt.get("d"));
662 }
663
664
665 @Test
666 public void testBigExponentLiterals() {
667 final JexlEvalContext ctxt = new JexlEvalContext();
668 final JexlOptions options = ctxt.getEngineOptions();
669 options.setStrictArithmetic(true);
670 final String stmt = "{a = 42.0e1B; b = 42.0E+2B; c = 42.0e-1B; d = 42.0E-2b; e=4242.4242e1b}";
671 final JexlScript expr = JEXL.createScript(stmt);
672 expr.execute(ctxt);
673 Assert.assertEquals(new BigDecimal("42.0e+1"), ctxt.get("a"));
674 Assert.assertEquals(new BigDecimal("42.0e+2"), ctxt.get("b"));
675 Assert.assertEquals(new BigDecimal("42.0e-1"), ctxt.get("c"));
676 Assert.assertEquals(new BigDecimal("42.0e-2"), ctxt.get("d"));
677 Assert.assertEquals(new BigDecimal("4242.4242e1"), ctxt.get("e"));
678 }
679
680
681 @Test
682 public void test2DoubleLiterals() {
683 final JexlEvalContext ctxt = new JexlEvalContext();
684 final JexlOptions options = ctxt.getEngineOptions();
685 options.setStrictArithmetic(true);
686 final String stmt = "{a = 42.0e1D; b = 42.0E+2D; c = 42.0e-1d; d = 42.0E-2d; e=10e10; f= +1.e1; g=1e1; }";
687 final JexlScript expr = JEXL.createScript(stmt);
688 expr.execute(ctxt);
689 Assert.assertEquals(Double.valueOf("42.0e+1"), ctxt.get("a"));
690 Assert.assertEquals(Double.valueOf("42.0e+2"), ctxt.get("b"));
691 Assert.assertEquals(Double.valueOf("42.0e-1"), ctxt.get("c"));
692 Assert.assertEquals(Double.valueOf("42.0e-2"), ctxt.get("d"));
693 Assert.assertEquals(Double.valueOf("10e10"), ctxt.get("e"));
694 Assert.assertEquals(Double.valueOf("10"), ctxt.get("f"));
695 Assert.assertEquals(Double.valueOf("10"), ctxt.get("g"));
696 }
697
698
699
700
701
702
703 @Test
704 public void testDivideByZero() throws Exception {
705 final Map<String, Object> vars = new HashMap<>();
706 final JexlEvalContext context = new JexlEvalContext(vars);
707 final JexlOptions options = context.getEngineOptions();
708 options.setStrictArithmetic(true);
709 vars.put("aByte", new Byte((byte) 1));
710 vars.put("aShort", new Short((short) 2));
711 vars.put("aInteger", new Integer(3));
712 vars.put("aLong", new Long(4));
713 vars.put("aFloat", new Float(5.5));
714 vars.put("aDouble", new Double(6.6));
715 vars.put("aBigInteger", new BigInteger("7"));
716 vars.put("aBigDecimal", new BigDecimal("8.8"));
717
718 vars.put("zByte", new Byte((byte) 0));
719 vars.put("zShort", new Short((short) 0));
720 vars.put("zInteger", new Integer(0));
721 vars.put("zLong", new Long(0));
722 vars.put("zFloat", new Float(0));
723 vars.put("zDouble", new Double(0));
724 vars.put("zBigInteger", new BigInteger("0"));
725 vars.put("zBigDecimal", new BigDecimal("0"));
726
727 final String[] tnames = {
728 "Byte", "Short", "Integer", "Long",
729 "Float", "Double",
730 "BigInteger", "BigDecimal"
731 };
732
733 final int PERMS = tnames.length * tnames.length;
734
735 final JexlEngine jexl = JEXL;
736
737 for (int s = 0; s < 2; ++s) {
738 final boolean strict = s != 0;
739 options.setStrict(true);
740 options.setStrictArithmetic(strict);
741 int zthrow = 0;
742 int zeval = 0;
743
744 for (final String vname : tnames) {
745
746 for (final String zname : tnames) {
747
748 final String expr = "a" + vname + " / " + "z" + zname;
749 try {
750 final JexlExpression zexpr = jexl.createExpression(expr);
751 final Object nan = zexpr.evaluate(context);
752
753 if (nan instanceof Number) {
754 final double zero = ((Number) nan).doubleValue();
755 if (zero == 0.0) {
756 zeval += 1;
757 }
758 }
759 } catch (final Exception any) {
760
761 zthrow += 1;
762 }
763 }
764 }
765 if (strict) {
766 Assert.assertEquals("All expressions should have thrown " + zthrow + "/" + PERMS, zthrow, PERMS);
767 } else {
768 Assert.assertEquals("All expressions should have zeroed " + zeval + "/" + PERMS, zeval, PERMS);
769 }
770 }
771 debuggerCheck(jexl);
772 }
773
774 @Test
775 public void testNaN() {
776 final Map<String, Object> ns = new HashMap<>();
777 ns.put("double", Double.class);
778 final JexlEngine jexl = new JexlBuilder().namespaces(ns).create();
779 JexlScript script;
780 Object result;
781 script = jexl.createScript("#NaN");
782 result = script.execute(null);
783 Assert.assertTrue(Double.isNaN((Double) result));
784 script = jexl.createScript("NaN");
785 result = script.execute(null);
786 Assert.assertTrue(Double.isNaN((Double) result));
787 script = jexl.createScript("double:isNaN(#NaN)");
788 result = script.execute(null);
789 Assert.assertTrue((Boolean) result);
790 script = jexl.createScript("double:isNaN(NaN)");
791 result = script.execute(null);
792 Assert.assertTrue((Boolean) result);
793 }
794
795
796
797
798 @Test
799 public void testMultClass(){
800 final JexlEngine jexl = new JexlBuilder().create();
801 final JexlContext jc = new MapContext();
802 final Object ra = jexl.createExpression("463.0d * 0.1").evaluate(jc);
803 Assert.assertEquals(Double.class, ra.getClass());
804 final Object r0 = jexl.createExpression("463.0B * 0.1").evaluate(jc);
805 Assert.assertEquals(java.math.BigDecimal.class, r0.getClass());
806 final Object r1 = jexl.createExpression("463.0B * 0.1B").evaluate(jc);
807 Assert.assertEquals(java.math.BigDecimal.class, r1.getClass());
808 }
809
810 @Test
811 public void testDivClass() {
812 final JexlEngine jexl = new JexlBuilder().create();
813 final JexlContext jc = new MapContext();
814 final Object ra = jexl.createExpression("463.0d / 0.1").evaluate(jc);
815 Assert.assertEquals(Double.class, ra.getClass());
816 final Object r0 = jexl.createExpression("463.0B / 0.1").evaluate(jc);
817 Assert.assertEquals(java.math.BigDecimal.class, r0.getClass());
818 final Object r1 = jexl.createExpression("463.0B / 0.1B").evaluate(jc);
819 Assert.assertEquals(java.math.BigDecimal.class, r1.getClass());
820 }
821
822 @Test
823 public void testPlusClass() {
824 final JexlEngine jexl = new JexlBuilder().create();
825 final JexlContext jc = new MapContext();
826 final Object ra = jexl.createExpression("463.0d + 0.1").evaluate(jc);
827 Assert.assertEquals(Double.class, ra.getClass());
828 final Object r0 = jexl.createExpression("463.0B + 0.1").evaluate(jc);
829 Assert.assertEquals(java.math.BigDecimal.class, r0.getClass());
830 final Object r1 = jexl.createExpression("463.0B + 0.1B").evaluate(jc);
831 Assert.assertEquals(java.math.BigDecimal.class, r1.getClass());
832 }
833
834 @Test
835 public void testMinusClass() {
836 final JexlEngine jexl = new JexlBuilder().create();
837 final JexlContext jc = new MapContext();
838 final Object ra = jexl.createExpression("463.0d - 0.1").evaluate(jc);
839 Assert.assertEquals(Double.class, ra.getClass());
840 final Object r0 = jexl.createExpression("463.0B - 0.1").evaluate(jc);
841 Assert.assertEquals(java.math.BigDecimal.class, r0.getClass());
842 final Object r1 = jexl.createExpression("463.0B - 0.1B").evaluate(jc);
843 Assert.assertEquals(java.math.BigDecimal.class, r1.getClass());
844 }
845
846 @Test
847 public void testAddWithStringsLenient() {
848 final JexlEngine jexl = new JexlBuilder().arithmetic(new JexlArithmetic(false)).create();
849 JexlScript script;
850 Object result;
851 script = jexl.createScript("'a' + 0");
852 result = script.execute(null);
853 Assert.assertEquals("a0", result);
854
855 script = jexl.createScript("0 + 'a' ");
856 result = script.execute(null);
857 Assert.assertEquals("0a", result);
858
859 script = jexl.createScript("0 + '1.2' ");
860 result = script.execute(null);
861 Assert.assertEquals(1.2d, (Double) result, EPSILON);
862
863 script = jexl.createScript("'1.2' + 1.2 ");
864 result = script.execute(null);
865 Assert.assertEquals(2.4d, (Double) result, EPSILON);
866
867 script = jexl.createScript("1.2 + 1.2 ");
868 result = script.execute(null);
869 Assert.assertEquals(2.4d, (Double) result, EPSILON);
870
871 script = jexl.createScript("1.2 + '1.2' ");
872 result = script.execute(null);
873 Assert.assertEquals(2.4d, (Double) result, EPSILON);
874
875 script = jexl.createScript("'1.2' + 0 ");
876 result = script.execute(null);
877 Assert.assertEquals(1.2d, (Double) result, EPSILON);
878
879 script = jexl.createScript("'1.2' + '1.2' ");
880 result = script.execute(null);
881 Assert.assertEquals("1.21.2", result);
882 }
883
884 @Test
885 public void testAddWithStringsStrict() {
886 final JexlEngine jexl = new JexlBuilder().arithmetic(new JexlArithmetic(true)).create();
887 JexlScript script;
888 Object result;
889 script = jexl.createScript("'a' + 0");
890 result = script.execute(null);
891 Assert.assertEquals("a0", result);
892
893 script = jexl.createScript("0 + 'a' ");
894 result = script.execute(null);
895 Assert.assertEquals("0a", result);
896
897 script = jexl.createScript("0 + '1.2' ");
898 result = script.execute(null);
899 Assert.assertEquals("01.2", result);
900
901 script = jexl.createScript("'1.2' + 1.2 ");
902 result = script.execute(null);
903 Assert.assertEquals("1.21.2", result);
904
905 script = jexl.createScript("1.2 + 1.2 ");
906 result = script.execute(null);
907 Assert.assertEquals(2.4d, (Double) result, EPSILON);
908
909 script = jexl.createScript("1.2 + '1.2' ");
910 result = script.execute(null);
911 Assert.assertEquals("1.21.2", result);
912
913 script = jexl.createScript("'1.2' + 0 ");
914 result = script.execute(null);
915 Assert.assertEquals("1.20", result);
916
917 script = jexl.createScript("'1.2' + '1.2' ");
918 result = script.execute(null);
919 Assert.assertEquals("1.21.2", result);
920
921 }
922
923 @Test
924 public void testNullArgs() {
925 JexlEngine jexl = new JexlBuilder().arithmetic(new JexlArithmetic(true) {
926 @Override public boolean isStrict(JexlOperator op) {
927 return JexlOperator.ADD == op? false: super.isStrict(op);
928 }
929 }).create();
930 JexlScript script = jexl.createScript("'1.2' + x ", "x");
931 Object result = script.execute(null);
932 Assert.assertEquals("1.2", result);
933 }
934
935 @Test
936 public void testOption() {
937 final Map<String, Object> vars = new HashMap<>();
938 final JexlEvalContext context = new JexlEvalContext(vars);
939 final JexlOptions options = context.getEngineOptions();
940 options.setStrictArithmetic(true);
941 final JexlScript script = JEXL.createScript("0 + '1.2' ");
942 Object result;
943
944 options.setStrictArithmetic(true);
945 result = script.execute(context);
946 Assert.assertEquals("01.2", result);
947
948 options.setStrictArithmetic(false);
949 result = script.execute(context);
950 Assert.assertEquals(1.2d, (Double) result, EPSILON);
951 }
952
953 @Test
954 public void testIsFloatingPointPattern() {
955 final JexlArithmetic ja = new JexlArithmetic(true);
956
957 Assert.assertFalse(ja.isFloatingPointNumber("floating point"));
958 Assert.assertFalse(ja.isFloatingPointNumber("a1."));
959 Assert.assertFalse(ja.isFloatingPointNumber("b1.2"));
960 Assert.assertFalse(ja.isFloatingPointNumber("-10.2a-34"));
961 Assert.assertFalse(ja.isFloatingPointNumber("+10.2a+34"));
962 Assert.assertFalse(ja.isFloatingPointNumber("0"));
963 Assert.assertFalse(ja.isFloatingPointNumber("1"));
964 Assert.assertFalse(ja.isFloatingPointNumber("12A"));
965 Assert.assertFalse(ja.isFloatingPointNumber("2F3"));
966 Assert.assertFalse(ja.isFloatingPointNumber("23"));
967 Assert.assertFalse(ja.isFloatingPointNumber("+3"));
968 Assert.assertFalse(ja.isFloatingPointNumber("+34"));
969 Assert.assertFalse(ja.isFloatingPointNumber("+3-4"));
970 Assert.assertFalse(ja.isFloatingPointNumber("+3.-4"));
971 Assert.assertFalse(ja.isFloatingPointNumber("3ee4"));
972
973 Assert.assertTrue(ja.isFloatingPointNumber("0."));
974 Assert.assertTrue(ja.isFloatingPointNumber("1."));
975 Assert.assertTrue(ja.isFloatingPointNumber("1.2"));
976 Assert.assertTrue(ja.isFloatingPointNumber("1.2e3"));
977 Assert.assertTrue(ja.isFloatingPointNumber("2e3"));
978 Assert.assertTrue(ja.isFloatingPointNumber("+2e-3"));
979 Assert.assertTrue(ja.isFloatingPointNumber("+23E-34"));
980 Assert.assertTrue(ja.isFloatingPointNumber("+23.E-34"));
981 Assert.assertTrue(ja.isFloatingPointNumber("-23.4E+45"));
982 Assert.assertTrue(ja.isFloatingPointNumber("1.2e34"));
983 Assert.assertTrue(ja.isFloatingPointNumber("10.2e34"));
984 Assert.assertTrue(ja.isFloatingPointNumber("+10.2e34"));
985 Assert.assertTrue(ja.isFloatingPointNumber("-10.2e34"));
986 Assert.assertTrue(ja.isFloatingPointNumber("10.2e-34"));
987 Assert.assertTrue(ja.isFloatingPointNumber("10.2e+34"));
988 Assert.assertTrue(ja.isFloatingPointNumber("-10.2e-34"));
989 Assert.assertTrue(ja.isFloatingPointNumber("+10.2e+34"));
990 Assert.assertTrue(ja.isFloatingPointNumber("-10.2E-34"));
991 Assert.assertTrue(ja.isFloatingPointNumber("+10.2E+34"));
992 }
993
994 public static class EmptyTestContext extends MapContext implements JexlContext.NamespaceResolver {
995 public static int log(final Object fmt, final Object... arr) {
996
997 return arr == null ? 0 : arr.length;
998 }
999
1000 public static int log(final Object fmt, final int... arr) {
1001
1002 return arr == null ? 0 : arr.length;
1003 }
1004
1005 @Override
1006 public Object resolveNamespace(final String name) {
1007 return this;
1008 }
1009 }
1010
1011 @Test
1012 public void testEmpty() throws Exception {
1013 final Object[] SCRIPTS = {
1014 "var x = null; log('x = %s', x);", 0,
1015 "var x = 'abc'; log('x = %s', x);", 1,
1016 "var x = 333; log('x = %s', x);", 1,
1017 "var x = [1, 2]; log('x = %s', x);", 2,
1018 "var x = ['a', 'b']; log('x = %s', x);", 2,
1019 "var x = {1:'A', 2:'B'}; log('x = %s', x);", 1,
1020 "var x = null; return empty(x);", true,
1021 "var x = ''; return empty(x);", true,
1022 "var x = 'abc'; return empty(x);", false,
1023 "var x = 0; return empty(x);", true,
1024 "var x = 333; return empty(x);", false,
1025 "var x = []; return empty(x);", true,
1026 "var x = [1, 2]; return empty(x);", false,
1027 "var x = ['a', 'b']; return empty(x);", false,
1028 "var x = [...]; return empty(x);", true,
1029 "var x = [1, 2,...]; return empty(x);", false,
1030 "var x = {:}; return empty(x);", true,
1031 "var x = {1:'A', 2:'B'}; return empty(x);", false,
1032 "var x = {}; return empty(x);", true,
1033 "var x = {'A','B'}; return empty(x);", false
1034 };
1035 final JexlEngine jexl = new JexlBuilder().create();
1036 final JexlContext jc = new EmptyTestContext();
1037 JexlScript script;
1038
1039 for (int e = 0; e < SCRIPTS.length; e += 2) {
1040 final String stext = (String) SCRIPTS[e];
1041 final Object expected = SCRIPTS[e + 1];
1042 script = jexl.createScript(stext);
1043 final Object result = script.execute(jc);
1044 Assert.assertEquals("failed on " + stext, expected, result);
1045 }
1046 }
1047
1048 public static class Var {
1049 int value;
1050
1051 Var(final int v) {
1052 value = v;
1053 }
1054
1055 @Override
1056 public String toString() {
1057 return Integer.toString(value);
1058 }
1059 }
1060
1061
1062 public static class ArithmeticPlus extends JexlArithmetic {
1063 public ArithmeticPlus(final boolean strict) {
1064 super(strict);
1065 }
1066
1067 public boolean equals(final Var lhs, final Var rhs) {
1068 return lhs.value == rhs.value;
1069 }
1070
1071 public boolean lessThan(final Var lhs, final Var rhs) {
1072 return lhs.value < rhs.value;
1073 }
1074
1075 public boolean lessThanOrEqual(final Var lhs, final Var rhs) {
1076 return lhs.value <= rhs.value;
1077 }
1078
1079 public boolean greaterThan(final Var lhs, final Var rhs) {
1080 return lhs.value > rhs.value;
1081 }
1082
1083 public boolean greaterThanOrEqual(final Var lhs, final Var rhs) {
1084 return lhs.value >= rhs.value;
1085 }
1086
1087 public Var add(final Var lhs, final Var rhs) {
1088 return new Var(lhs.value + rhs.value);
1089 }
1090
1091 public Var subtract(final Var lhs, final Var rhs) {
1092 return new Var(lhs.value - rhs.value);
1093 }
1094
1095 public Var divide(final Var lhs, final Var rhs) {
1096 return new Var(lhs.value / rhs.value);
1097 }
1098
1099 public Var multiply(final Var lhs, final Var rhs) {
1100 return new Var(lhs.value * rhs.value);
1101 }
1102
1103 public Var mod(final Var lhs, final Var rhs) {
1104 return new Var(lhs.value / rhs.value);
1105 }
1106
1107 public Var negate(final Var arg) {
1108 return new Var(-arg.value);
1109 }
1110
1111 public Var and(final Var lhs, final Var rhs) {
1112 return new Var(lhs.value & rhs.value);
1113 }
1114
1115 public Var or(final Var lhs, final Var rhs) {
1116 return new Var(lhs.value | rhs.value);
1117 }
1118
1119 public Var xor(final Var lhs, final Var rhs) {
1120 return new Var(lhs.value ^ rhs.value);
1121 }
1122
1123 public Var shiftRight(final Var lhs, final Var rhs) {
1124 return new Var(lhs.value >> rhs.value);
1125 }
1126
1127 public Var shiftRightUnsigned(final Var lhs, final Var rhs) {
1128 return new Var(lhs.value >>> rhs.value);
1129 }
1130
1131 public Var shiftLeft(final Var lhs, final Var rhs) {
1132 return new Var(lhs.value << rhs.value);
1133 }
1134
1135 public Boolean contains(final Var lhs, final Var rhs) {
1136 return lhs.toString().contains(rhs.toString());
1137 }
1138
1139 public Boolean startsWith(final Var lhs, final Var rhs) {
1140 return lhs.toString().startsWith(rhs.toString());
1141 }
1142
1143 public Boolean endsWith(final Var lhs, final Var rhs) {
1144 return lhs.toString().endsWith(rhs.toString());
1145 }
1146
1147 public Var complement(final Var arg) {
1148 return new Var(~arg.value);
1149 }
1150
1151 public Object subtract(final String x, final String y) {
1152 final int ix = x.indexOf(y);
1153 if (ix < 0) {
1154 return x;
1155 }
1156 final StringBuilder strb = new StringBuilder(x.substring(0, ix));
1157 strb.append(x.substring(ix + y.length()));
1158 return strb.toString();
1159 }
1160
1161 public Object negate(final String str) {
1162 final int length = str.length();
1163 final StringBuilder strb = new StringBuilder(str.length());
1164 for (int c = length - 1; c >= 0; --c) {
1165 strb.append(str.charAt(c));
1166 }
1167 return strb.toString();
1168 }
1169
1170 public Object not(final Var x) {
1171 throw new NullPointerException("make it fail");
1172 }
1173 }
1174
1175 @Test
1176 public void testArithmeticPlus() throws Exception {
1177 final JexlEngine jexl = new JexlBuilder().cache(64).arithmetic(new ArithmeticPlus(false)).create();
1178 final JexlContext jc = new EmptyTestContext();
1179 runOverload(jexl, jc);
1180 runOverload(jexl, jc);
1181 }
1182
1183 @Test
1184 public void testArithmeticPlusNoCache() {
1185 final JexlEngine jexl = new JexlBuilder().cache(0).arithmetic(new ArithmeticPlus(false)).create();
1186 final JexlContext jc = new EmptyTestContext();
1187 runOverload(jexl, jc);
1188 }
1189
1190 protected void runOverload(final JexlEngine jexl, final JexlContext jc) {
1191 JexlScript script;
1192 Object result;
1193
1194 script = jexl.createScript("(x, y)->{ x < y }");
1195 result = script.execute(jc, 42, 43);
1196 Assert.assertEquals(true, result);
1197 result = script.execute(jc, new Var(42), new Var(43));
1198 Assert.assertEquals(true, result);
1199 result = script.execute(jc, new Var(42), new Var(43));
1200 Assert.assertEquals(true, result);
1201 result = script.execute(jc, 43, 42);
1202 Assert.assertEquals(false, result);
1203 result = script.execute(jc, new Var(43), new Var(42));
1204 Assert.assertEquals(false, result);
1205
1206 script = jexl.createScript("(x, y)->{ x <= y }");
1207 result = script.execute(jc, 42, 43);
1208 Assert.assertEquals(true, result);
1209 result = script.execute(jc, new Var(42), new Var(43));
1210 Assert.assertEquals(true, result);
1211 result = script.execute(jc, new Var(41), new Var(44));
1212 Assert.assertEquals(true, result);
1213 result = script.execute(jc, 43, 42);
1214 Assert.assertEquals(false, result);
1215 result = script.execute(jc, new Var(45), new Var(40));
1216 Assert.assertEquals(false, result);
1217
1218 script = jexl.createScript("(x, y)->{ x > y }");
1219 result = script.execute(jc, 42, 43);
1220 Assert.assertEquals(false, result);
1221 result = script.execute(jc, new Var(42), new Var(43));
1222 Assert.assertEquals(false, result);
1223 result = script.execute(jc, new Var(42), new Var(43));
1224 Assert.assertEquals(false, result);
1225 result = script.execute(jc, 43, 42);
1226 Assert.assertEquals(true, result);
1227 result = script.execute(jc, new Var(43), new Var(42));
1228 Assert.assertEquals(true, result);
1229
1230 script = jexl.createScript("(x, y)->{ x >= y }");
1231 result = script.execute(jc, 42, 43);
1232 Assert.assertEquals(false, result);
1233 result = script.execute(jc, new Var(42), new Var(43));
1234 Assert.assertEquals(false, result);
1235 result = script.execute(jc, new Var(41), new Var(44));
1236 Assert.assertEquals(false, result);
1237 result = script.execute(jc, 43, 42);
1238 Assert.assertEquals(true, result);
1239 result = script.execute(jc, new Var(45), new Var(40));
1240 Assert.assertEquals(true, result);
1241
1242 script = jexl.createScript("(x, y)->{ x == y }");
1243 result = script.execute(jc, 42, 43);
1244 Assert.assertEquals(false, result);
1245 result = script.execute(jc, new Var(42), new Var(43));
1246 Assert.assertEquals(false, result);
1247 result = script.execute(jc, new Var(41), new Var(44));
1248 Assert.assertEquals(false, result);
1249 result = script.execute(jc, 43, 42);
1250 Assert.assertEquals(false, result);
1251 result = script.execute(jc, new Var(45), new Var(40));
1252 Assert.assertEquals(false, result);
1253
1254 script = jexl.createScript("(x, y)->{ x != y }");
1255 result = script.execute(jc, 42, 43);
1256 Assert.assertEquals(true, result);
1257 result = script.execute(jc, new Var(42), new Var(43));
1258 Assert.assertEquals(true, result);
1259 result = script.execute(jc, new Var(44), new Var(44));
1260 Assert.assertEquals(false, result);
1261 result = script.execute(jc, 44, 44);
1262 Assert.assertEquals(false, result);
1263 result = script.execute(jc, new Var(45), new Var(40));
1264 Assert.assertEquals(true, result);
1265
1266 script = jexl.createScript("(x, y)->{ x % y }");
1267 result = script.execute(jc, 4242, 100);
1268 Assert.assertEquals(42, result);
1269 result = script.execute(jc, new Var(4242), new Var(100));
1270 Assert.assertEquals(42, ((Var) result).value);
1271
1272 script = jexl.createScript("(x, y)->{ x * y }");
1273 result = script.execute(jc, 6, 7);
1274 Assert.assertEquals(42, result);
1275 result = script.execute(jc, new Var(6), new Var(7));
1276 Assert.assertEquals(42, ((Var) result).value);
1277
1278 script = jexl.createScript("(x, y)->{ x + y }");
1279 result = script.execute(jc, 35, 7);
1280 Assert.assertEquals(42, result);
1281 result = script.execute(jc, new Var(35), new Var(7));
1282 Assert.assertEquals(42, ((Var) result).value);
1283
1284 script = jexl.createScript("(x, y)->{ x - y }");
1285 result = script.execute(jc, 49, 7);
1286 Assert.assertEquals(42, result);
1287 result = script.execute(jc, "foobarquux", "bar");
1288 Assert.assertEquals("fooquux", result);
1289 result = script.execute(jc, 50, 8);
1290 Assert.assertEquals(42, result);
1291 result = script.execute(jc, new Var(50), new Var(8));
1292 Assert.assertEquals(42, ((Var) result).value);
1293
1294 script = jexl.createScript("(x)->{ -x }");
1295 result = script.execute(jc, -42);
1296 Assert.assertEquals(42, result);
1297 result = script.execute(jc, new Var(-42));
1298 Assert.assertEquals(42, ((Var) result).value);
1299 result = script.execute(jc, "pizza");
1300 Assert.assertEquals("azzip", result);
1301 result = script.execute(jc, -142);
1302 Assert.assertEquals(142, result);
1303
1304 script = jexl.createScript("(x)->{ ~x }");
1305 result = script.execute(jc, -1);
1306 Assert.assertEquals(0L, result);
1307 result = script.execute(jc, new Var(-1));
1308 Assert.assertEquals(0L, ((Var) result).value);
1309 result = script.execute(jc, new Var(-42));
1310 Assert.assertEquals(41, ((Var) result).value);
1311
1312 script = jexl.createScript("(x, y)->{ x ^ y }");
1313 result = script.execute(jc, 35, 7);
1314 Assert.assertEquals(36L, result);
1315 result = script.execute(jc, new Var(35), new Var(7));
1316 Assert.assertEquals(36L, ((Var) result).value);
1317
1318 script = jexl.createScript("(x, y)->bitwiseXor(x,y)");
1319 result = script.execute(jc, 35, 7);
1320 Assert.assertEquals(36L, result);
1321
1322 script = jexl.createScript("(x, y)->{ x | y }");
1323 result = script.execute(jc, 35, 7);
1324 Assert.assertEquals(39L, result);
1325 result = script.execute(jc, new Var(35), new Var(7));
1326 Assert.assertEquals(39L, ((Var) result).value);
1327
1328 script = jexl.createScript("(x, y)->bitwiseOr(x,y)");
1329 result = script.execute(jc, 35, 7);
1330 Assert.assertEquals(39L, result);
1331
1332 script = jexl.createScript("(x, y)->{ x << y }");
1333 result = script.execute(jc, 35, 1);
1334 Assert.assertEquals(70L, result);
1335 result = script.execute(jc, new Var(35), new Var(1));
1336 Assert.assertEquals(70L, ((Var) result).value);
1337
1338 script = jexl.createScript("(x, y)->{ x >> y }");
1339 result = script.execute(jc, 42, 1);
1340 Assert.assertEquals(21L, result);
1341 result = script.execute(jc, new Var(42), new Var(1));
1342 Assert.assertEquals(21, ((Var) result).value);
1343
1344 script = jexl.createScript("(x, y)->{ x >>> y }");
1345 result = script.execute(jc, 84, 2);
1346 Assert.assertEquals(21L, result);
1347 result = script.execute(jc, new Var(84), new Var(2));
1348 Assert.assertEquals(21, ((Var) result).value);
1349
1350 script = jexl.createScript("(x, y)->{ x & y }");
1351 result = script.execute(jc, 35, 7);
1352 Assert.assertEquals(3L, result);
1353 result = script.execute(jc, new Var(35), new Var(7));
1354 Assert.assertEquals(3L, ((Var) result).value);
1355
1356 script = jexl.createScript("(x, y)->bitwiseAnd(x,y)");
1357 result = script.execute(jc, 35, 7);
1358 Assert.assertEquals(3L, result);
1359
1360 script = jexl.createScript("(x, y)->{ x =^ y }");
1361 result = script.execute(jc, 3115, 31);
1362 Assert.assertFalse((Boolean) result);
1363 result = script.execute(jc, new Var(3115), new Var(31));
1364 Assert.assertTrue((Boolean) result);
1365
1366 script = jexl.createScript("(x, y)->{ x !^ y }");
1367 result = script.execute(jc, 3115, 31);
1368 Assert.assertTrue((Boolean) result);
1369 result = script.execute(jc, new Var(3115), new Var(31));
1370 Assert.assertFalse((Boolean) result);
1371
1372 script = jexl.createScript("(x, y)->{ x =$ y }");
1373 result = script.execute(jc, 3115, 15);
1374 Assert.assertFalse((Boolean) result);
1375 result = script.execute(jc, new Var(3115), new Var(15));
1376 Assert.assertTrue((Boolean) result);
1377
1378 script = jexl.createScript("(x, y)->{ x !$ y }");
1379 result = script.execute(jc, 3115, 15);
1380 Assert.assertTrue((Boolean) result);
1381 result = script.execute(jc, new Var(3115), new Var(15));
1382 Assert.assertFalse((Boolean) result);
1383
1384 script = jexl.createScript("(x, y)->{ x =~ y }");
1385 result = script.execute(jc, 3155, 15);
1386 Assert.assertFalse((Boolean) result);
1387 result = script.execute(jc, new Var(3155), new Var(15));
1388 Assert.assertFalse((Boolean) result);
1389 result = script.execute(jc, new Var(15), new Var(3155));
1390 Assert.assertTrue((Boolean) result);
1391
1392 script = jexl.createScript("(x, y)->{ x !~ y }");
1393 result = script.execute(jc, 3115, 15);
1394 Assert.assertTrue((Boolean) result);
1395 result = script.execute(jc, new Var(3155), new Var(15));
1396 Assert.assertTrue((Boolean) result);
1397 result = script.execute(jc, new Var(15), new Var(3155));
1398 Assert.assertFalse((Boolean) result);
1399
1400 script = jexl.createScript("(x)->{ !x }");
1401 try {
1402 result = script.execute(jc, new Var(-42));
1403 Assert.fail("should fail");
1404 } catch (final JexlException xany) {
1405 Assert.assertTrue(xany instanceof JexlException.Operator);
1406 }
1407 }
1408
1409 public static class Callable173 {
1410 public Object call(final String... arg) {
1411 return 42;
1412 }
1413 public Object call(final Integer... arg) {
1414 return arg[0] * arg[1];
1415 }
1416 }
1417
1418 @Test
1419 public void testJexl173() {
1420 final JexlEngine jexl = new JexlBuilder().create();
1421 final JexlContext jc = new MapContext();
1422 final Callable173 c173 = new Callable173();
1423 JexlScript e = jexl.createScript( "c173(9, 6)", "c173" );
1424 Object result = e.execute(jc, c173);
1425 Assert.assertEquals(54, result);
1426 e = jexl.createScript( "c173('fourty', 'two')", "c173" );
1427 result = e.execute(jc, c173);
1428 Assert.assertEquals(42, result);
1429
1430 }
1431
1432 public static class Arithmetic132 extends JexlArithmetic {
1433 public Arithmetic132() {
1434 super(false);
1435 }
1436
1437 protected double divideZero(final BigDecimal x) {
1438 final int ls = x.signum();
1439 if (ls < 0) {
1440 return Double.NEGATIVE_INFINITY;
1441 }
1442 if (ls > 0) {
1443 return Double.POSITIVE_INFINITY;
1444 }
1445 return Double.NaN;
1446 }
1447
1448 protected double divideZero(final BigInteger x) {
1449 final int ls = x.signum();
1450 if (ls < 0) {
1451 return Double.NEGATIVE_INFINITY;
1452 }
1453 if (ls > 0) {
1454 return Double.POSITIVE_INFINITY;
1455 }
1456 return Double.NaN;
1457 }
1458
1459 @Override
1460 public Object divide(final Object left, final Object right) {
1461 if (left == null && right == null) {
1462 return controlNullNullOperands(JexlOperator.DIVIDE);
1463 }
1464
1465 if (left instanceof BigDecimal || right instanceof BigDecimal) {
1466 final BigDecimal l = toBigDecimal(left);
1467 final BigDecimal r = toBigDecimal(right);
1468 if (BigDecimal.ZERO.equals(r)) {
1469 return divideZero(l);
1470 }
1471 final BigDecimal result = l.divide(r, getMathContext());
1472 return narrowBigDecimal(left, right, result);
1473 }
1474
1475 if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
1476 final double l = toDouble(left);
1477 final double r = toDouble(right);
1478 return new Double(l / r);
1479 }
1480
1481 final BigInteger l = toBigInteger(left);
1482 final BigInteger r = toBigInteger(right);
1483 if (BigInteger.ZERO.equals(r)) {
1484 return divideZero(l);
1485 }
1486 final BigInteger result = l.divide(r);
1487 return narrowBigInteger(left, right, result);
1488 }
1489
1490 @Override
1491 public Object mod(final Object left, final Object right) {
1492 if (left == null && right == null) {
1493 return controlNullNullOperands(JexlOperator.MOD);
1494 }
1495
1496 if (left instanceof BigDecimal || right instanceof BigDecimal) {
1497 final BigDecimal l = toBigDecimal(left);
1498 final BigDecimal r = toBigDecimal(right);
1499 if (BigDecimal.ZERO.equals(r)) {
1500 return divideZero(l);
1501 }
1502 final BigDecimal remainder = l.remainder(r, getMathContext());
1503 return narrowBigDecimal(left, right, remainder);
1504 }
1505
1506 if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
1507 final double l = toDouble(left);
1508 final double r = toDouble(right);
1509 return new Double(l % r);
1510 }
1511
1512 final BigInteger l = toBigInteger(left);
1513 final BigInteger r = toBigInteger(right);
1514 final BigInteger result = l.mod(r);
1515 if (BigInteger.ZERO.equals(r)) {
1516 return divideZero(l);
1517 }
1518 return narrowBigInteger(left, right, result);
1519 }
1520 }
1521
1522 @Test
1523 public void testInfiniteArithmetic() throws Exception {
1524 final Map<String, Object> ns = new HashMap<>();
1525 ns.put("math", Math.class);
1526 final JexlEngine jexl = new JexlBuilder().arithmetic(new Arithmetic132()).namespaces(ns).create();
1527
1528 Object evaluate = jexl.createExpression("1/0").evaluate(null);
1529 Assert.assertTrue(Double.isInfinite((Double) evaluate));
1530
1531 evaluate = jexl.createExpression("-1/0").evaluate(null);
1532 Assert.assertTrue(Double.isInfinite((Double) evaluate));
1533
1534 evaluate = jexl.createExpression("1.0/0.0").evaluate(null);
1535 Assert.assertTrue(Double.isInfinite((Double) evaluate));
1536
1537 evaluate = jexl.createExpression("-1.0/0.0").evaluate(null);
1538 Assert.assertTrue(Double.isInfinite((Double) evaluate));
1539
1540 evaluate = jexl.createExpression("math:abs(-42)").evaluate(null);
1541 Assert.assertEquals(42, evaluate);
1542 }
1543
1544 private static Document getDocument(final String xml) throws Exception {
1545 final DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
1546 final InputStream stringInputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
1547 return xmlBuilder.parse(stringInputStream);
1548 }
1549
1550 public static class XmlArithmetic extends JexlArithmetic {
1551 public XmlArithmetic(final boolean astrict) {
1552 super(astrict);
1553 }
1554
1555 public XmlArithmetic(final boolean astrict, final MathContext bigdContext, final int bigdScale) {
1556 super(astrict, bigdContext, bigdScale);
1557 }
1558
1559 public boolean empty(final org.w3c.dom.Element elt) {
1560 return !elt.hasAttributes() && !elt.hasChildNodes();
1561 }
1562
1563 public int size(final org.w3c.dom.Element elt) {
1564 return elt.getChildNodes().getLength();
1565 }
1566 }
1567
1568
1569
1570
1571 @Test
1572 public void testXmlArithmetic() throws Exception {
1573 Document xml;
1574 Node x;
1575 Boolean empty;
1576 int size;
1577 final JexlEvalContext ctxt = new JexlEvalContext();
1578 final JexlEngine jexl = new JexlBuilder().strict(true).safe(false).arithmetic(new XmlArithmetic(false)).create();
1579 final JexlScript e0 = jexl.createScript("x.empty()", "x");
1580 final JexlScript e1 = jexl.createScript("empty(x)", "x");
1581 final JexlScript s0 = jexl.createScript("x.size()", "x");
1582 final JexlScript s1 = jexl.createScript("size(x)", "x");
1583
1584 empty = (Boolean) e1.execute(null, (Object) null);
1585 Assert.assertTrue(empty);
1586 size = (Integer) s1.execute(null, (Object) null);
1587 Assert.assertEquals(0, size);
1588
1589 try {
1590 final Object xx = e0.execute(null, (Object) null);
1591 Assert.assertNull(xx);
1592 } catch (final JexlException.Variable xvar) {
1593 Assert.assertNotNull(xvar);
1594 }
1595 try {
1596 final Object xx = s0.execute(null, (Object) null);
1597 Assert.assertNull(xx);
1598 } catch (final JexlException.Variable xvar) {
1599 Assert.assertNotNull(xvar);
1600 }
1601 final JexlOptions options = ctxt.getEngineOptions();
1602 options.setSafe(true);
1603 final Object x0 = e0.execute(ctxt, (Object) null);
1604 Assert.assertNull(x0);
1605 final Object x1 = s0.execute(ctxt, (Object) null);
1606 Assert.assertNull(x1);
1607
1608 xml = getDocument("<node info='123'/>");
1609 x = xml.getLastChild();
1610 empty = (Boolean) e0.execute(null, x);
1611 Assert.assertFalse(empty);
1612 empty = (Boolean) e1.execute(null, x);
1613 Assert.assertFalse(empty);
1614 size = (Integer) s0.execute(null, x);
1615 Assert.assertEquals(0, size);
1616 size = (Integer) s1.execute(null, x);
1617 Assert.assertEquals(0, size);
1618 xml = getDocument("<node><a/><b/></node>");
1619 x = xml.getLastChild();
1620 empty = (Boolean) e0.execute(null, x);
1621 Assert.assertFalse(empty);
1622 empty = (Boolean) e1.execute(null, x);
1623 Assert.assertFalse(empty);
1624 size = (Integer) s0.execute(null, x);
1625 Assert.assertEquals(2, size);
1626 size = (Integer) s1.execute(null, x);
1627 Assert.assertEquals(2, size);
1628 xml = getDocument("<node/>");
1629 x = xml.getLastChild();
1630 empty = (Boolean) e0.execute(null, x);
1631 Assert.assertTrue(empty);
1632 empty = (Boolean) e1.execute(null, x);
1633 Assert.assertTrue(empty);
1634 size = (Integer) s0.execute(null, x);
1635 Assert.assertEquals(0, size);
1636 size = (Integer) s1.execute(null, x);
1637 Assert.assertEquals(0, size);
1638 xml = getDocument("<node info='123'/>");
1639 NamedNodeMap nnm = xml.getLastChild().getAttributes();
1640 Attr info = (Attr) nnm.getNamedItem("info");
1641 Assert.assertEquals("123", info.getValue());
1642
1643
1644 final JexlContext jc = new MapContext();
1645 jc.set("x", xml.getLastChild());
1646 final String y = "456";
1647 jc.set("y", y);
1648 final JexlScript s = jexl.createScript("x.attribute.info = y");
1649 Object r;
1650 try {
1651 r = s.execute(jc);
1652 nnm = xml.getLastChild().getAttributes();
1653 info = (Attr) nnm.getNamedItem("info");
1654 Assert.assertEquals(y, r);
1655 Assert.assertEquals(y, info.getValue());
1656 } catch(JexlException.Property xprop) {
1657
1658 Assert.assertTrue(xprop.getMessage().contains("info"));
1659 Assert.assertTrue(getJavaVersion() > 11);
1660 }
1661 }
1662
1663
1664
1665
1666
1667 private static int getJavaVersion() {
1668 String version = System.getProperty("java.version");
1669 if (version.startsWith("1.")) {
1670 version = version.substring(2);
1671 }
1672 int sep = version.indexOf(".");
1673 if (sep < 0) {
1674 sep = version.indexOf("-");
1675 }
1676 if (sep > 0) {
1677 version = version.substring(0, sep);
1678 }
1679 return Integer.parseInt(version);
1680 }
1681
1682 @Test
1683 public void testEmptyLong() {
1684 Object x;
1685 x = JEXL.createScript("new('java.lang.Long', 4294967296)").execute(null);
1686 Assert.assertEquals(4294967296L, ((Long) x).longValue());
1687 x = JEXL.createScript("new Long(4294967296)").execute(null);
1688 Assert.assertEquals(4294967296L, ((Long) x).longValue());
1689 x = JEXL.createScript("new('java.lang.Long', '4294967296')").execute(null);
1690 Assert.assertEquals(4294967296L, ((Long) x).longValue());
1691 x = JEXL.createScript("4294967296l").execute(null);
1692 Assert.assertEquals(4294967296L, ((Long) x).longValue());
1693 x = JEXL.createScript("4294967296L").execute(null);
1694 Assert.assertEquals(4294967296L, ((Long) x).longValue());
1695 checkEmpty(x, false);
1696 x = JEXL.createScript("0L").execute(null);
1697 Assert.assertEquals(0, ((Long) x).longValue());
1698 checkEmpty(x, true);
1699 }
1700
1701 @Test
1702 public void testEmptyFloat() {
1703 Object x;
1704 x = JEXL.createScript("4294967296.f").execute(null);
1705 Assert.assertEquals(4294967296.0f, (Float) x, EPSILON);
1706 checkEmpty(x, false);
1707 x = JEXL.createScript("4294967296.0f").execute(null);
1708 Assert.assertEquals(4294967296.0f, (Float) x, EPSILON);
1709 checkEmpty(x, false);
1710 x = JEXL.createScript("0.0f").execute(null);
1711 Assert.assertEquals(0.0f, (Float) x, EPSILON);
1712 checkEmpty(x, true);
1713 x = Float.NaN;
1714 checkEmpty(x, true);
1715 }
1716
1717 @Test
1718 public void testEmptyDouble() {
1719 Object x;
1720 x = JEXL.createScript("4294967296.d").execute(null);
1721 Assert.assertEquals(4294967296.0d, (Double) x, EPSILON);
1722 checkEmpty(x, false);
1723 x = JEXL.createScript("4294967296.0d").execute(null);
1724 Assert.assertEquals(4294967296.0d, (Double) x, EPSILON);
1725 checkEmpty(x, false);
1726 x = JEXL.createScript("0.0d").execute(null);
1727 Assert.assertEquals(0.0d, (Double) x, EPSILON);
1728 checkEmpty(x, true);
1729 x = Double.NaN;
1730 checkEmpty(x, true);
1731
1732 }
1733
1734 void checkEmpty(final Object x, final boolean expect) {
1735 final JexlScript s0 = JEXL.createScript("empty(x)", "x");
1736 boolean empty = (Boolean) s0.execute(null, x);
1737 Assert.assertEquals(expect, empty);
1738 final JexlScript s1 = JEXL.createScript("empty x", "x");
1739 empty = (Boolean) s1.execute(null, x);
1740 Assert.assertEquals(expect, empty);
1741 final JexlScript s2 = JEXL.createScript("x.empty()", "x");
1742 empty = (Boolean) s2.execute(null, x);
1743 Assert.assertEquals(expect, empty);
1744 }
1745
1746 @Test
1747 public void testCoerceInteger() {
1748 final JexlArithmetic ja = JEXL.getArithmetic();
1749 final JexlEvalContext ctxt = new JexlEvalContext();
1750 final JexlOptions options = ctxt.getEngineOptions();
1751 options.setStrictArithmetic(true);
1752 final String stmt = "a = 34L; b = 45.0D; c=56.0F; d=67B; e=78H;";
1753 final JexlScript expr = JEXL.createScript(stmt);
1754 expr.execute(ctxt);
1755 Assert.assertEquals(34, ja.toInteger(ctxt.get("a")));
1756 Assert.assertEquals(45, ja.toInteger(ctxt.get("b")));
1757 Assert.assertEquals(56, ja.toInteger(ctxt.get("c")));
1758 Assert.assertEquals(67, ja.toInteger(ctxt.get("d")));
1759 Assert.assertEquals(78, ja.toInteger(ctxt.get("e")));
1760 Assert.assertEquals(10, ja.toInteger("10"));
1761 Assert.assertEquals(1, ja.toInteger(true));
1762 Assert.assertEquals(0, ja.toInteger(false));
1763 }
1764
1765 @Test
1766 public void testCoerceLong() {
1767 final JexlArithmetic ja = JEXL.getArithmetic();
1768 final JexlEvalContext ctxt = new JexlEvalContext();
1769 final JexlOptions options = ctxt.getEngineOptions();
1770 options.setStrictArithmetic(true);
1771 final String stmt = "a = 34L; b = 45.0D; c=56.0F; d=67B; e=78H;";
1772 final JexlScript expr = JEXL.createScript(stmt);
1773 expr.execute(ctxt);
1774 Assert.assertEquals(34L, ja.toLong(ctxt.get("a")));
1775 Assert.assertEquals(45L, ja.toLong(ctxt.get("b")));
1776 Assert.assertEquals(56L, ja.toLong(ctxt.get("c")));
1777 Assert.assertEquals(67L, ja.toLong(ctxt.get("d")));
1778 Assert.assertEquals(78L, ja.toLong(ctxt.get("e")));
1779 Assert.assertEquals(10L, ja.toLong("10"));
1780 Assert.assertEquals(1L, ja.toLong(true));
1781 Assert.assertEquals(0L, ja.toLong(false));
1782 }
1783
1784 @Test
1785 public void testCoerceDouble() {
1786 final JexlArithmetic ja = JEXL.getArithmetic();
1787 final JexlEvalContext ctxt = new JexlEvalContext();
1788 final JexlOptions options = ctxt.getEngineOptions();
1789 options.setStrictArithmetic(true);
1790 final String stmt = "{a = 34L; b = 45.0D; c=56.0F; d=67B; e=78H; }";
1791 final JexlScript expr = JEXL.createScript(stmt);
1792 expr.execute(ctxt);
1793 Assert.assertEquals(34, ja.toDouble(ctxt.get("a")), EPSILON);
1794 Assert.assertEquals(45, ja.toDouble(ctxt.get("b")), EPSILON);
1795 Assert.assertEquals(56, ja.toDouble(ctxt.get("c")), EPSILON);
1796 Assert.assertEquals(67, ja.toDouble(ctxt.get("d")), EPSILON);
1797 Assert.assertEquals(78, ja.toDouble(ctxt.get("e")), EPSILON);
1798 Assert.assertEquals(10d, ja.toDouble("10"), EPSILON);
1799 Assert.assertEquals(1.D, ja.toDouble(true), EPSILON);
1800 Assert.assertEquals(0.D, ja.toDouble(false), EPSILON);
1801 }
1802
1803 @Test
1804 public void testCoerceBigInteger() {
1805 final JexlArithmetic ja = JEXL.getArithmetic();
1806 final JexlEvalContext ctxt = new JexlEvalContext();
1807 final JexlOptions options = ctxt.getEngineOptions();
1808 options.setStrictArithmetic(true);
1809 final String stmt = "{a = 34L; b = 45.0D; c=56.0F; d=67B; e=78H; }";
1810 final JexlScript expr = JEXL.createScript(stmt);
1811 expr.execute(ctxt);
1812 Assert.assertEquals(BigInteger.valueOf(34), ja.toBigInteger(ctxt.get("a")));
1813 Assert.assertEquals(BigInteger.valueOf(45), ja.toBigInteger(ctxt.get("b")));
1814 Assert.assertEquals(BigInteger.valueOf(56), ja.toBigInteger(ctxt.get("c")));
1815 Assert.assertEquals(BigInteger.valueOf(67), ja.toBigInteger(ctxt.get("d")));
1816 Assert.assertEquals(BigInteger.valueOf(78), ja.toBigInteger(ctxt.get("e")));
1817 Assert.assertEquals(BigInteger.valueOf(10), ja.toBigInteger("10"));
1818 Assert.assertEquals(BigInteger.valueOf(1), ja.toBigInteger(true));
1819 Assert.assertEquals(BigInteger.valueOf(0), ja.toBigInteger(false));
1820 }
1821
1822 @Test
1823 public void testCoerceBigDecimal() {
1824 final JexlArithmetic ja = JEXL.getArithmetic();
1825 final JexlEvalContext ctxt = new JexlEvalContext();
1826 final JexlOptions options = ctxt.getEngineOptions();
1827 options.setStrictArithmetic(true);
1828 final String stmt = "{a = 34L; b = 45.0D; c=56.0F; d=67B; e=78H; }";
1829 final JexlScript expr = JEXL.createScript(stmt);
1830 expr.execute(ctxt);
1831 Assert.assertEquals(BigDecimal.valueOf(34), ja.toBigDecimal(ctxt.get("a")));
1832 Assert.assertEquals(BigDecimal.valueOf(45.), ja.toBigDecimal(ctxt.get("b")));
1833 Assert.assertEquals(BigDecimal.valueOf(56.), ja.toBigDecimal(ctxt.get("c")));
1834 Assert.assertEquals(BigDecimal.valueOf(67), ja.toBigDecimal(ctxt.get("d")));
1835 Assert.assertEquals(BigDecimal.valueOf(78), ja.toBigDecimal(ctxt.get("e")));
1836 Assert.assertEquals(BigDecimal.valueOf(10), ja.toBigDecimal("10"));
1837 Assert.assertEquals(BigDecimal.valueOf(1.), ja.toBigDecimal(true));
1838 Assert.assertEquals(BigDecimal.valueOf(0.), ja.toBigDecimal(false));
1839 }
1840
1841 @Test
1842 public void testAtomicBoolean() {
1843
1844 JexlScript e = JEXL.createScript("if (x) 1 else 2;", "x");
1845 final JexlContext jc = new MapContext();
1846 final AtomicBoolean ab = new AtomicBoolean(false);
1847 Object o;
1848 o = e.execute(jc, ab);
1849 Assert.assertEquals("Result is not 2", new Integer(2), o);
1850 ab.set(true);
1851 o = e.execute(jc, ab);
1852 Assert.assertEquals("Result is not 1", new Integer(1), o);
1853
1854 e = JEXL.createScript("x && y", "x", "y");
1855 ab.set(true);
1856 o = e.execute(jc, ab, Boolean.FALSE);
1857 Assert.assertFalse((Boolean) o);
1858 ab.set(true);
1859 o = e.execute(jc, ab, Boolean.TRUE);
1860 Assert.assertTrue((Boolean) o);
1861 ab.set(false);
1862 o = e.execute(jc, ab, Boolean.FALSE);
1863 Assert.assertFalse((Boolean) o);
1864 ab.set(false);
1865 o = e.execute(jc, ab, Boolean.FALSE);
1866 Assert.assertFalse((Boolean) o);
1867
1868 e = JEXL.createScript("x + y", "x", "y");
1869 ab.set(true);
1870 o = e.execute(jc, ab, 10);
1871 Assert.assertEquals(11, o);
1872 o = e.execute(jc, 10, ab);
1873 Assert.assertEquals(11, o);
1874 o = e.execute(jc, ab, 10.d);
1875 Assert.assertEquals(11.d, (Double) o, EPSILON);
1876 o = e.execute(jc, 10.d, ab);
1877 Assert.assertEquals(11.d, (Double) o, EPSILON);
1878
1879 final BigInteger bi10 = BigInteger.TEN;
1880 ab.set(false);
1881 o = e.execute(jc, ab, bi10);
1882 Assert.assertEquals(bi10, o);
1883 o = e.execute(jc, bi10, ab);
1884 Assert.assertEquals(bi10, o);
1885
1886 final BigDecimal bd10 = BigDecimal.TEN;
1887 ab.set(false);
1888 o = e.execute(jc, ab, bd10);
1889 Assert.assertEquals(bd10, o);
1890 o = e.execute(jc, bd10, ab);
1891 Assert.assertEquals(bd10, o);
1892
1893
1894 e = JEXL.createScript("!x", "x");
1895 ab.set(true);
1896 o = e.execute(jc, ab);
1897 Assert.assertFalse((Boolean) o);
1898 ab.set(false);
1899 o = e.execute(jc, ab);
1900 Assert.assertTrue((Boolean) o);
1901
1902
1903 e = JEXL.createScript("-x", "x");
1904 ab.set(true);
1905 o = e.execute(jc, ab);
1906 Assert.assertFalse((Boolean) o);
1907 ab.set(false);
1908 o = e.execute(jc, ab);
1909 Assert.assertTrue((Boolean) o);
1910 }
1911
1912 @Test
1913 public void testCompare() {
1914
1915 final Object[] EXPRESSIONS = {
1916
1917 "1 == 1", true,
1918 "1 != 1", false,
1919 "1 != 2", true,
1920 "1 > 2", false,
1921 "1 >= 2", false,
1922 "1 < 2", true,
1923 "1 <= 2", true,
1924
1925 "1.0 == 1", true,
1926 "1 == 1.0", true,
1927 "1.1 != 1", true,
1928 "1.1 < 2", true,
1929
1930 "1.0b == 1h", true,
1931 "1h == 1.0b", true,
1932 "1.1b != 1h", true,
1933 "1.1b < 2h", true,
1934
1935 "1l == 1.0", true,
1936 "1.0d == 1.0f", true,
1937 "1l == 1.0b", true,
1938 "1l == 1h", true,
1939 "1.0d == 1.0b", true,
1940 "1.0f == 1.0b", true,
1941 "1.0d == 1h", true,
1942 "1.0f == 1h", true,
1943
1944 "'1' == 1", true,
1945 "'1' == 1l", true,
1946 "'1' == 1h", true,
1947 "'' == 0", true,
1948 "'1.0' == 1", true,
1949 "'1.0' == 1.0f", true,
1950 "'1.0' == 1.0d", true,
1951 "'1.0' == 1.0b", true,
1952 "'1.01' == 1.01", true,
1953 "'1.01' == 1", false,
1954 "'1.01' == 1b", false,
1955 "'1.01' == 1h", false,
1956 "'1.00001' == 1b", false,
1957 "'1.00001' == 1h", false,
1958 "'1.00000001' == 1", false,
1959 "'1.00000001' == 1b", false,
1960 "'1.00000001' == 1h", false,
1961 "1.0 >= '1'", true,
1962 "1.0 > '1'", false,
1963 };
1964 final JexlEngine jexl = new JexlBuilder().create();
1965 final JexlContext jc = new EmptyTestContext();
1966 JexlExpression expression;
1967
1968 for (int e = 0; e < EXPRESSIONS.length; e += 2) {
1969 final String stext = (String) EXPRESSIONS[e];
1970 final Object expected = EXPRESSIONS[e + 1];
1971 expression = jexl.createExpression(stext);
1972 final Object result = expression.evaluate(jc);
1973 Assert.assertEquals("failed on " + stext, expected, result);
1974 }
1975 }
1976 }