1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jexl3;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.SortedSet;
28 import java.util.TreeSet;
29 import java.util.Calendar;
30 import java.util.Date;
31 import java.util.Locale;
32 import java.util.TimeZone;
33
34 import org.apache.commons.jexl3.junit.Asserter;
35 import java.io.StringWriter;
36 import java.text.DecimalFormat;
37 import java.text.SimpleDateFormat;
38
39 import org.junit.Assert;
40 import org.junit.Before;
41 import org.junit.Test;
42
43
44
45
46
47 @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
48 public class ArithmeticOperatorTest extends JexlTestCase {
49 private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
50 private Asserter asserter;
51
52 @Before
53 @Override
54 public void setUp() {
55 asserter = new Asserter(JEXL);
56 asserter.setStrict(false);
57 }
58
59
60
61
62 public ArithmeticOperatorTest() {
63 super("ArithmeticOperatorTest");
64 }
65
66 @Test
67 public void testRegexp() throws Exception {
68 asserter.setVariable("str", "abc456");
69 asserter.assertExpression("str =~ '.*456'", Boolean.TRUE);
70 asserter.assertExpression("str !~ 'ABC.*'", Boolean.TRUE);
71 asserter.setVariable("match", "abc.*");
72 asserter.setVariable("nomatch", ".*123");
73 asserter.assertExpression("str =~ match", Boolean.TRUE);
74 asserter.assertExpression("str !~ match", Boolean.FALSE);
75 asserter.assertExpression("str !~ nomatch", Boolean.TRUE);
76 asserter.assertExpression("str =~ nomatch", Boolean.FALSE);
77 asserter.setVariable("match", new StringBuilder("abc.*"));
78 asserter.setVariable("nomatch", new StringBuilder(".*123"));
79 asserter.assertExpression("str =~ match", Boolean.TRUE);
80 asserter.assertExpression("str !~ match", Boolean.FALSE);
81 asserter.assertExpression("str !~ nomatch", Boolean.TRUE);
82 asserter.assertExpression("str =~ nomatch", Boolean.FALSE);
83 asserter.setVariable("match", java.util.regex.Pattern.compile("abc.*"));
84 asserter.setVariable("nomatch", java.util.regex.Pattern.compile(".*123"));
85 asserter.assertExpression("str =~ match", Boolean.TRUE);
86 asserter.assertExpression("str !~ match", Boolean.FALSE);
87 asserter.assertExpression("str !~ nomatch", Boolean.TRUE);
88 asserter.assertExpression("str =~ nomatch", Boolean.FALSE);
89
90 asserter.assertExpression("'a' =~ ['a','b','c','d','e','f']", Boolean.TRUE);
91 asserter.assertExpression("'a' !~ ['a','b','c','d','e','f']", Boolean.FALSE);
92 asserter.assertExpression("'z' =~ ['a','b','c','d','e','f']", Boolean.FALSE);
93 asserter.assertExpression("'z' !~ ['a','b','c','d','e','f']", Boolean.TRUE);
94 }
95
96 @Test
97 public void test391() throws Exception {
98
99 for(String src : Arrays.asList(
100 "2 =~ [1, 2, 3, 4]",
101 "[2, 3] =~ [1, 2, 3, 4]",
102 "[2, 3,...] =~ [1, 2, 3, 4]",
103 "3 =~ [1, 2, 3, 4,...]",
104 "[2, 3] =~ [1, 2, 3, 4,...]",
105 "[2, 3,...] =~ [1, 2, 3, 4,...]")) {
106 asserter.assertExpression(src, Boolean.TRUE);
107 }
108
109 int[] ic = new int[]{1, 2, 3, 4};
110 List<Integer> iic = new ArrayList<>();
111 for(int v : ic) { iic.add(v); }
112 int[] iv = new int[]{2, 3};
113 List<Integer> iiv = new ArrayList<>();
114 for(int v : iv) { iiv.add(v); }
115 String src = "(x,y) -> x =~ y ";
116 for(Object v : Arrays.asList(iv, iiv, 2)) {
117 for(Object c : Arrays.asList(ic, iic)) {
118 asserter.assertExpression(src, Boolean.TRUE, v, c);
119 }
120 }
121 }
122
123 @Test
124 public void testRegexp2() throws Exception {
125 asserter.setVariable("str", "abc456");
126 asserter.assertExpression("str =~ ~/.*456/", Boolean.TRUE);
127 asserter.assertExpression("str !~ ~/ABC.*/", Boolean.TRUE);
128 asserter.assertExpression("str =~ ~/abc\\d{3}/", Boolean.TRUE);
129
130 asserter.assertExpression("matches(str, ~/.*456/)", Boolean.TRUE);
131 asserter.setVariable("str", "4/6");
132 asserter.assertExpression("str =~ ~/\\d\\/\\d/", Boolean.TRUE);
133 }
134
135 @Test
136 public void testStartsEndsWithString() throws Exception {
137 asserter.setVariable("x", "foobar");
138 asserter.assertExpression("x =^ 'foo'", Boolean.TRUE);
139 asserter.assertExpression("x =$ 'foo'", Boolean.FALSE);
140 asserter.setVariable("x", "barfoo");
141 asserter.assertExpression("x =^ 'foo'", Boolean.FALSE);
142 asserter.assertExpression("x =$ 'foo'", Boolean.TRUE);
143 }
144
145 @Test
146 public void testStartsEndsWithStringDot() throws Exception {
147 asserter.setVariable("x.y", "foobar");
148 asserter.assertExpression("x.y =^ 'foo'", Boolean.TRUE);
149 asserter.assertExpression("x.y =$ 'foo'", Boolean.FALSE);
150 asserter.setVariable("x.y", "barfoo");
151 asserter.assertExpression("x.y =^ 'foo'", Boolean.FALSE);
152 asserter.assertExpression("x.y =$ 'foo'", Boolean.TRUE);
153 }
154
155 @Test
156 public void testNotStartsEndsWithString() throws Exception {
157 asserter.setVariable("x", "foobar");
158 asserter.assertExpression("x !^ 'foo'", Boolean.FALSE);
159 asserter.assertExpression("x !$ 'foo'", Boolean.TRUE);
160 asserter.setVariable("x", "barfoo");
161 asserter.assertExpression("x !^ 'foo'", Boolean.TRUE);
162 asserter.assertExpression("x !$ 'foo'", Boolean.FALSE);
163 }
164
165 @Test
166 public void testNotStartsEndsWithStringDot() throws Exception {
167 asserter.setVariable("x.y", "foobar");
168 asserter.assertExpression("x.y !^ 'foo'", Boolean.FALSE);
169 asserter.assertExpression("x.y !$ 'foo'", Boolean.TRUE);
170 asserter.setVariable("x.y", "barfoo");
171 asserter.assertExpression("x.y !^ 'foo'", Boolean.TRUE);
172 asserter.assertExpression("x.y !$ 'foo'", Boolean.FALSE);
173 }
174
175 @Test
176 public void testStartsEndsWithStringBuilder() throws Exception {
177 asserter.setVariable("x", new StringBuilder("foobar"));
178 asserter.assertExpression("x =^ 'foo'", Boolean.TRUE);
179 asserter.assertExpression("x =$ 'foo'", Boolean.FALSE);
180 asserter.setVariable("x", new StringBuilder("barfoo"));
181 asserter.assertExpression("x =^ 'foo'", Boolean.FALSE);
182 asserter.assertExpression("x =$ 'foo'", Boolean.TRUE);
183 }
184
185 @Test
186 public void testNotStartsEndsWithStringBuilder() throws Exception {
187 asserter.setVariable("x", new StringBuilder("foobar"));
188 asserter.assertExpression("x !^ 'foo'", Boolean.FALSE);
189 asserter.assertExpression("x !$ 'foo'", Boolean.TRUE);
190 asserter.setVariable("x", new StringBuilder("barfoo"));
191 asserter.assertExpression("x !^ 'foo'", Boolean.TRUE);
192 asserter.assertExpression("x !$ 'foo'", Boolean.FALSE);
193 }
194
195 public static class MatchingContainer {
196 private final Set<Integer> values;
197
198 public MatchingContainer(final int[] is) {
199 values = new HashSet<>();
200 for (final int value : is) {
201 values.add(value);
202 }
203 }
204
205 public boolean contains(final int value) {
206 return values.contains(value);
207 }
208 }
209
210 public static class IterableContainer implements Iterable<Integer> {
211 private final SortedSet<Integer> values;
212
213 public IterableContainer(final int[] is) {
214 values = new TreeSet<>();
215 for (final int value : is) {
216 values.add(value);
217 }
218 }
219
220 @Override
221 public Iterator<Integer> iterator() {
222 return values.iterator();
223 }
224
225 public boolean contains(final int i) {
226 return values.contains(i);
227 }
228
229 public boolean contains(final int[] i) {
230 for(int ii : i) if (!values.contains(ii)) return false;
231 return true;
232 }
233
234 public boolean startsWith(final int i) {
235 return values.first().equals(i);
236 }
237
238 public boolean endsWith(final int i) {
239 return values.last().equals(i);
240 }
241
242 public boolean startsWith(final int[] i) {
243 final SortedSet<Integer> sw = values.headSet(i.length);
244 int n = 0;
245 for(final Integer value : sw) {
246 if(!value.equals(i[n++])) {
247 return false;
248 }
249 }
250 return true;
251 }
252 public boolean endsWith(final int[] i) {
253 final SortedSet<Integer> sw = values.tailSet(values.size() - i.length);
254 int n = 0;
255 for(final Integer value : sw) {
256 if(!value.equals(i[n++])) {
257 return false;
258 }
259 }
260 return true;
261 }
262 }
263
264 @Test
265 public void testMatch() throws Exception {
266
267 final int[] ai = {2, 4, 42, 54};
268 final List<Integer> al = new ArrayList<>();
269 for (final int i : ai) {
270 al.add(i);
271 }
272 final Map<Integer, String> am = new HashMap<>();
273 am.put(2, "two");
274 am.put(4, "four");
275 am.put(42, "forty-two");
276 am.put(54, "fifty-four");
277 final MatchingContainer ad = new MatchingContainer(ai);
278 final IterableContainer ic = new IterableContainer(ai);
279 final Set<Integer> as = ad.values;
280 final Object[] vars = {ai, al, am, ad, as, ic};
281
282 for (final Object var : vars) {
283 asserter.setVariable("container", var);
284 for (final int x : ai) {
285 asserter.setVariable("x", x);
286 asserter.assertExpression("x =~ container", Boolean.TRUE);
287 }
288 asserter.setVariable("x", 169);
289 asserter.assertExpression("x !~ container", Boolean.TRUE);
290 }
291 }
292
293 @Test
294 public void testStartsEndsWith() throws Exception {
295 asserter.setVariable("x", "foobar");
296 asserter.assertExpression("x =^ 'foo'", Boolean.TRUE);
297 asserter.assertExpression("x =$ 'foo'", Boolean.FALSE);
298 asserter.setVariable("x", "barfoo");
299 asserter.assertExpression("x =^ 'foo'", Boolean.FALSE);
300 asserter.assertExpression("x =$ 'foo'", Boolean.TRUE);
301
302 final int[] ai = {2, 4, 42, 54};
303 final IterableContainer ic = new IterableContainer(ai);
304 asserter.setVariable("x", ic);
305 asserter.assertExpression("x =^ 2", Boolean.TRUE);
306 asserter.assertExpression("x =$ 54", Boolean.TRUE);
307 asserter.assertExpression("x =^ 4", Boolean.FALSE);
308 asserter.assertExpression("x =$ 42", Boolean.FALSE);
309 asserter.assertExpression("x =^ [2, 4]", Boolean.TRUE);
310 asserter.assertExpression("x =^ [42, 54]", Boolean.TRUE);
311 }
312
313 @Test
314 public void testNotStartsEndsWith() throws Exception {
315 asserter.setVariable("x", "foobar");
316 asserter.assertExpression("x !^ 'foo'", Boolean.FALSE);
317 asserter.assertExpression("x !$ 'foo'", Boolean.TRUE);
318 asserter.setVariable("x", "barfoo");
319 asserter.assertExpression("x !^ 'foo'", Boolean.TRUE);
320 asserter.assertExpression("x !$ 'foo'", Boolean.FALSE);
321
322 final int[] ai = {2, 4, 42, 54};
323 final IterableContainer ic = new IterableContainer(ai);
324 asserter.setVariable("x", ic);
325 asserter.assertExpression("x !^ 2", Boolean.FALSE);
326 asserter.assertExpression("x !$ 54", Boolean.FALSE);
327 asserter.assertExpression("x !^ 4", Boolean.TRUE);
328 asserter.assertExpression("x !$ 42", Boolean.TRUE);
329 asserter.assertExpression("x !^ [2, 4]", Boolean.FALSE);
330 asserter.assertExpression("x !^ [42, 54]", Boolean.FALSE);
331 }
332
333 public static class Aggregate {
334 private Aggregate() {}
335 public static int sum(final Iterable<Integer> ii) {
336 int sum = 0;
337 for(final Integer i : ii) {
338 sum += i;
339 }
340 return sum;
341 }
342 }
343
344 @Test
345 @SuppressWarnings("unchecked")
346 public void testInterval() throws Exception {
347 final Map<String, Object> ns = new HashMap<>();
348 ns.put("calc", Aggregate.class);
349 final JexlEngine jexl = new JexlBuilder().namespaces(ns).create();
350 JexlScript script;
351 Object result;
352
353 script = jexl.createScript("1 .. 3");
354 result = script.execute(null);
355 Assert.assertTrue(result instanceof Iterable<?>);
356 Iterator<Integer> ii = ((Iterable<Integer>) result).iterator();
357 Assert.assertEquals(Integer.valueOf(1), ii.next());
358 Assert.assertEquals(Integer.valueOf(2), ii.next());
359 Assert.assertEquals(Integer.valueOf(3), ii.next());
360
361 script = jexl.createScript("(4 - 3) .. (9 / 3)");
362 result = script.execute(null);
363 Assert.assertTrue(result instanceof Iterable<?>);
364 ii = ((Iterable<Integer>) result).iterator();
365 Assert.assertEquals(Integer.valueOf(1), ii.next());
366 Assert.assertEquals(Integer.valueOf(2), ii.next());
367 Assert.assertEquals(Integer.valueOf(3), ii.next());
368
369
370 script = jexl.createScript("var x = 0; for(var y : ((5 - 4) .. (12 / 4))) { x = x + y }; x");
371 result = script.execute(null);
372 Assert.assertEquals(Integer.valueOf(6), result);
373
374 script = jexl.createScript("calc:sum(1 .. 3)");
375 result = script.execute(null);
376 Assert.assertEquals(Integer.valueOf(6), result);
377
378 script = jexl.createScript("calc:sum(-3 .. 3)");
379 result = script.execute(null);
380 Assert.assertEquals(Integer.valueOf(0), result);
381 }
382
383 public static class DateArithmetic extends JexlArithmetic {
384 DateArithmetic(final boolean flag) {
385 super(flag);
386 }
387
388 protected Object getDateValue(final Date date, final String key) {
389 try {
390 final Calendar cal = Calendar.getInstance(UTC);
391 cal.setTime(date);
392 if ("yyyy".equals(key)) {
393 return cal.get(Calendar.YEAR);
394 }
395 if ("MM".equals(key)) {
396 return cal.get(Calendar.MONTH) + 1;
397 }
398 if ("dd".equals(key)) {
399 return cal.get(Calendar.DAY_OF_MONTH);
400 }
401
402 final SimpleDateFormat df = new SimpleDateFormat(key);
403 return df.format(date);
404
405 } catch (final Exception ex) {
406 return null;
407 }
408 }
409
410 protected Object setDateValue(final Date date, final String key, final Object value) throws Exception {
411 final Calendar cal = Calendar.getInstance(UTC);
412 cal.setTime(date);
413 if ("yyyy".equals(key)) {
414 cal.set(Calendar.YEAR, toInteger(value));
415 } else if ("MM".equals(key)) {
416 cal.set(Calendar.MONTH, toInteger(value) - 1);
417 } else if ("dd".equals(key)) {
418 cal.set(Calendar.DAY_OF_MONTH, toInteger(value));
419 }
420 date.setTime(cal.getTimeInMillis());
421 return date;
422 }
423
424 public Object propertyGet(final Date date, final String identifier) {
425 return getDateValue(date, identifier);
426 }
427
428 public Object propertySet(final Date date, final String identifier, final Object value) throws Exception {
429 return setDateValue(date, identifier, value);
430 }
431
432 public Object arrayGet(final Date date, final String identifier) {
433 return getDateValue(date, identifier);
434 }
435
436 public Object arraySet(final Date date, final String identifier, final Object value) throws Exception {
437 return setDateValue(date, identifier, value);
438 }
439
440 public Date now() {
441 return new Date(System.currentTimeMillis());
442 }
443
444 public Date multiply(final Date d0, final Date d1) {
445 throw new ArithmeticException("unsupported");
446 }
447 }
448
449 public static class DateContext extends MapContext {
450 private Locale locale = Locale.US;
451
452 void setLocale(final Locale l10n) {
453 this.locale = l10n;
454 }
455
456 public String format(final Date date, final String fmt) {
457 final SimpleDateFormat sdf = new SimpleDateFormat(fmt, locale);
458 sdf.setTimeZone(UTC);
459 return sdf.format(date);
460 }
461
462 public String format(final Number number, final String fmt) {
463 return new DecimalFormat(fmt).format(number);
464 }
465 }
466
467 @Test
468 public void testOperatorError() throws Exception {
469 testOperatorError(true);
470 testOperatorError(false);
471 }
472
473 private void testOperatorError(final boolean silent) throws Exception {
474 final CaptureLog log = new CaptureLog();
475 final DateContext jc = new DateContext();
476 final Date d = new Date();
477 final JexlEngine jexl = new JexlBuilder().logger(log).strict(true).silent(silent).cache(32)
478 .arithmetic(new DateArithmetic(true)).create();
479 final JexlScript expr0 = jexl.createScript("date * date", "date");
480 try {
481 final Object value0 = expr0.execute(jc, d);
482 if (!silent) {
483 Assert.fail("should have failed");
484 } else {
485 Assert.assertEquals(1, log.count("warn"));
486 }
487 } catch(final JexlException.Operator xop) {
488 Assert.assertEquals("*", xop.getSymbol());
489 }
490 if (!silent) {
491 Assert.assertEquals(0, log.count("warn"));
492 }
493 }
494
495 @Test
496 public void testDateArithmetic() throws Exception {
497 final Date d = new Date();
498 final JexlContext jc = new MapContext();
499 final JexlEngine jexl = new JexlBuilder().cache(32).arithmetic(new DateArithmetic(true)).create();
500 final JexlScript expr0 = jexl.createScript("date.yyyy = 1969; date.MM=7; date.dd=20; ", "date");
501 Object value0 = expr0.execute(jc, d);
502 Assert.assertNotNull(value0);
503 value0 = d;
504
505 Assert.assertEquals(1969, jexl.createScript("date.yyyy", "date").execute(jc, value0));
506 Assert.assertEquals(7, jexl.createScript("date.MM", "date").execute(jc, value0));
507 Assert.assertEquals(20, jexl.createScript("date.dd", "date").execute(jc, value0));
508 }
509
510 @Test
511 public void testFormatArithmetic() throws Exception {
512 final Calendar cal = Calendar.getInstance(UTC);
513 cal.set(1969, Calendar.AUGUST, 20);
514 final Date x0 = cal.getTime();
515 final String y0 = "MM/yy/dd";
516 final Number x1 = 42.12345;
517 final String y1 = "##0.##";
518 final DateContext jc = new DateContext();
519 final JexlEngine jexl = new JexlBuilder().cache(32).arithmetic(new DateArithmetic(true)).create();
520 final JexlScript expr0 = jexl.createScript("x.format(y)", "x", "y");
521 Object value10 = expr0.execute(jc, x0, y0);
522 final Object value20 = expr0.execute(jc, x0, y0);
523 Assert.assertEquals(value10, value20);
524 Object value11 = expr0.execute(jc, x1, y1);
525 final Object value21 = expr0.execute(jc, x1, y1);
526 Assert.assertEquals(value11, value21);
527 value10 = expr0.execute(jc, x0, y0);
528 Assert.assertEquals(value10, value20);
529 value11 = expr0.execute(jc, x1, y1);
530 Assert.assertEquals(value11, value21);
531 value10 = expr0.execute(jc, x0, y0);
532 Assert.assertEquals(value10, value20);
533 value11 = expr0.execute(jc, x1, y1);
534 Assert.assertEquals(value11, value21);
535
536 JexlScript expr1 = jexl.createScript("format(x, y)", "x", "y");
537 value10 = expr1.execute(jc, x0, y0);
538 Assert.assertEquals(value10, value20);
539 Object s0 = expr1.execute(jc, x0, "EEE dd MMM yyyy");
540 Assert.assertEquals("Wed 20 Aug 1969", s0);
541 jc.setLocale(Locale.FRANCE);
542 s0 = expr1.execute(jc, x0, "EEE dd MMM yyyy");
543 Assert.assertEquals("mer. 20 ao\u00fbt 1969", s0);
544
545 expr1 = jexl.createScript("format(now(), y)", "y");
546 final Object n0 = expr1.execute(jc, y0);
547 Assert.assertNotNull(n0);
548 expr1 = jexl.createScript("now().format(y)", "y");
549 final Object n1 = expr1.execute(jc, y0);
550 Assert.assertNotNull(n0);
551 Assert.assertEquals(n0, n1);
552 }
553
554 @Test
555 public void testFormatArithmeticJxlt() throws Exception {
556 final Map<String, Object> ns = new HashMap<>();
557 ns.put("calc", Aggregate.class);
558 final Calendar cal = Calendar.getInstance(UTC);
559 cal.set(1969, Calendar.AUGUST, 20);
560 final Date x0 = cal.getTime();
561 final String y0 = "yyyy-MM-dd";
562 final DateContext jc = new DateContext();
563 final JexlEngine jexl = new JexlBuilder().cache(32).namespaces(ns).arithmetic(new DateArithmetic(true)).create();
564 final JxltEngine jxlt = jexl.createJxltEngine();
565
566 JxltEngine.Template expr0 = jxlt.createTemplate("${x.format(y)}", "x", "y");
567 StringWriter strw = new StringWriter();
568 expr0.evaluate(jc, strw, x0, y0);
569 String strws = strw.toString();
570 Assert.assertEquals("1969-08-20", strws);
571
572 expr0 = jxlt.createTemplate("${calc:sum(x .. y)}", "x", "y");
573 strw = new StringWriter();
574 expr0.evaluate(jc, strw, 1, 3);
575 strws = strw.toString();
576 Assert.assertEquals("6", strws);
577
578 final JxltEngine.Template expr1 = jxlt.createTemplate("${jexl:include(s, x, y)}", "s", "x", "y");
579 strw = new StringWriter();
580 expr1.evaluate(jc, strw, expr0, 1, 3);
581 strws = strw.toString();
582 Assert.assertEquals("6", strws);
583
584 expr0 = jxlt.createTemplate("${now().format(y)}", "y");
585 strw = new StringWriter();
586 expr0.evaluate(jc, strw, y0);
587 strws = strw.toString();
588 Assert.assertNotNull(strws);
589 }
590
591 @Test public void test373a() {
592 testSelfAssignOperators("y.add(x++)", 42, 42, 43);
593 }
594 @Test public void test373b() {
595 testSelfAssignOperators("y.add(++x)", 42, 43, 43);
596 }
597 @Test public void test373c() {
598 testSelfAssignOperators("y.add(x--)", 42, 42, 41);
599 }
600 @Test public void test373d() {
601 testSelfAssignOperators("y.add(--x)", 42, 41, 41);
602 }
603
604 void testSelfAssignOperators(String text, int x, int y0, int x0) {
605
606 JexlEngine jexl = new JexlBuilder().safe(true).create();
607 JexlScript script = jexl.createScript(text);
608 JexlContext context = new MapContext();
609 context.set("x", x);
610 List<Number> y = new ArrayList<>();
611 context.set("y", y);
612 Object result = script.execute(context);
613 Assert.assertEquals("x0", x0, context.get("x"));
614 Assert.assertEquals("y0", y0, y.get(0));
615 }
616
617 @Test
618 public void testIncrementOperatorOnNull() throws Exception {
619 final JexlEngine jexl = new JexlBuilder().strict(false).create();
620 JexlScript script;
621 Object result;
622 script = jexl.createScript("var i = null; ++i");
623 result = script.execute(null);
624 Assert.assertEquals(1, result);
625 script = jexl.createScript("var i = null; --i");
626 result = script.execute(null);
627 Assert.assertEquals(-1, result);
628 }
629
630 }