View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.io.File;
28  import java.math.BigDecimal;
29  import java.math.MathContext;
30  import java.net.URL;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Set;
38  
39  import org.apache.commons.jexl3.internal.Engine;
40  import org.junit.jupiter.api.BeforeEach;
41  import org.junit.jupiter.api.Test;
42  
43  /**
44   * Test cases for reported issue between JEXL-100 and JEXL-199.
45   */
46  @SuppressWarnings({"boxing", "UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
47  class Issues100Test extends JexlTestCase {
48      // A's class definition
49      public static class A105 {
50          String nameA;
51          String propA;
52  
53          public A105(final String nameA, final String propA) {
54              this.nameA = nameA;
55              this.propA = propA;
56          }
57  
58          public String getNameA() {
59              return nameA;
60          }
61  
62          public String getPropA() {
63              return propA;
64          }
65  
66          @Override
67          public String toString() {
68              return "A [nameA=" + nameA + ", propA=" + propA + "]";
69          }
70  
71          public String uppercase(final String str) {
72              return str.toUpperCase();
73          }
74      }
75  
76      public static class Arithmetic42 extends JexlArithmetic {
77          public Arithmetic42() {
78              super(false);
79          }
80  
81          public Object and(final String lhs, final String rhs) {
82              if (rhs.isEmpty() || lhs.isEmpty()) {
83                  return "";
84              }
85              return lhs + rhs;
86          }
87  
88          public Object or(final String lhs, final String rhs) {
89              if (rhs.isEmpty()) {
90                  return lhs;
91              }
92              if (lhs.isEmpty()) {
93                  return rhs;
94              }
95              return lhs + rhs;
96          }
97      }
98  
99      public static class C192 {
100         public static Integer callme(final Integer n) {
101             if (n == null) {
102                 return null;
103             }
104             return n >= 0 ? 42 : -42;
105         }
106 
107         public static Object kickme() {
108             return C192.class;
109         }
110 
111         public C192() {
112         }
113     }
114 
115 public static class Foo125 {
116         public String method() {
117             return "OK";
118         }
119 
120         public String total(final String tt) {
121             return "total " + tt;
122         }
123     }
124 
125     public static class Foo125Context extends ObjectContext<Foo125> {
126         public Foo125Context(final JexlEngine engine, final Foo125 wrapped) {
127             super(engine, wrapped);
128         }
129     }
130 
131     public static class Question42 extends MapContext {
132         public String functionA(final String arg) {
133             return "a".equals(arg) ? "A" : "";
134         }
135 
136         public String functionB(final String arg) {
137             return "b".equals(arg) ? "B" : "";
138         }
139 
140         public String functionC(final String arg) {
141             return "c".equals(arg) ? "C" : "";
142         }
143 
144         public String functionD(final String arg) {
145             return "d".equals(arg) ? "D" : "";
146         }
147     }
148 
149     /**
150      * Test cases for empty array assignment.
151      */
152     public static class Quux144 {
153         String[] arr;
154         String[] arr2;
155 
156         public Quux144() {
157         }
158 
159         public String[] getArr() {
160             return arr;
161         }
162 
163         public String[] getArr2() {
164             return arr2;
165         }
166 
167         public void setArr(final String[] arr) {
168             this.arr = arr;
169         }
170 
171         // Overloaded setter with different argument type.
172         public void setArr2(final Integer[] arr2) {
173         }
174 
175         public void setArr2(final String[] arr2) {
176             this.arr2 = arr2;
177         }
178     }
179 
180     public static class RichContext extends ObjectContext<A105> {
181         RichContext(final JexlEngine jexl, final A105 a105) {
182             super(jexl, a105);
183         }
184     }
185 
186     public static class Utils {
187         public List<Integer> asList(final int[] array) {
188             final List<Integer> l = new ArrayList<>(array.length);
189             for (final int i : array) {
190                 l.add(i);
191             }
192             return l;
193         }
194 
195         public <T> List<T> asList(final T[] array) {
196             return Arrays.asList(array);
197         }
198     }
199 
200     static final String TESTA = "src/test/scripts/testA.jexl";
201 
202     public Issues100Test() {
203         super("Issues100Test", null);
204     }
205 
206     @BeforeEach
207     @Override
208     public void setUp() throws Exception {
209         // ensure jul logging is only error to avoid warning in silent mode
210         java.util.logging.Logger.getLogger(JexlEngine.class.getName()).setLevel(java.util.logging.Level.SEVERE);
211     }
212 
213     @Test
214     void test100() throws Exception {
215         final JexlEngine jexl = new JexlBuilder().cache(4).create();
216         final JexlContext ctxt = new MapContext();
217         final int[] foo = {42};
218         ctxt.set("foo", foo);
219         Object value;
220         for (int l = 0; l < 2; ++l) {
221             value = jexl.createExpression("foo[0]").evaluate(ctxt);
222             assertEquals(42, value);
223             value = jexl.createExpression("foo[0] = 43").evaluate(ctxt);
224             assertEquals(43, value);
225             value = jexl.createExpression("foo.0").evaluate(ctxt);
226             assertEquals(43, value);
227             value = jexl.createExpression("foo.0 = 42").evaluate(ctxt);
228             assertEquals(42, value);
229         }
230     }
231 
232     @Test
233     void test105() throws Exception {
234         final JexlContext context = new MapContext();
235         final JexlExpression selectExp = new Engine().createExpression("[a.propA]");
236         context.set("a", new A105("a1", "p1"));
237         Object[] r = (Object[]) selectExp.evaluate(context);
238         assertEquals("p1", r[0]);
239 
240 //selectExp = new Engine().createExpression("[a.propA]");
241         context.set("a", new A105("a2", "p2"));
242         r = (Object[]) selectExp.evaluate(context);
243         assertEquals("p2", r[0]);
244     }
245 
246     @Test
247     void test106() throws Exception {
248         final JexlEvalContext context = new JexlEvalContext();
249         final JexlOptions options = context.getEngineOptions();
250         options.setStrict(true);
251         options.setStrictArithmetic(true);
252         context.set("a", new BigDecimal(1));
253         context.set("b", new BigDecimal(3));
254         final JexlEngine jexl = new Engine();
255         final Object value = jexl.createExpression("a / b").evaluate(context);
256         assertNotNull(value);
257         options.setMathContext(MathContext.UNLIMITED);
258         options.setMathScale(2);
259         assertThrows(JexlException.class, () -> jexl.createExpression("a / b").evaluate(context));
260     }
261 
262     @Test
263     void test107() throws Exception {
264         // @formatter:off
265         final String[] exprs = {
266             "'Q4'.toLowerCase()", "q4",
267             "(Q4).toLowerCase()", "q4",
268             "(4).toString()", "4",
269             "(1 + 3).toString()", "4",
270             "({ 'q' : 'Q4'}).get('q').toLowerCase()", "q4",
271             "{ 'q' : 'Q4'}.get('q').toLowerCase()", "q4",
272             "({ 'q' : 'Q4'})['q'].toLowerCase()", "q4",
273             "(['Q4'])[0].toLowerCase()", "q4"
274         };
275         // @formatter:on
276         final JexlContext context = new MapContext();
277         context.set("Q4", "Q4");
278         final JexlEngine jexl = new Engine();
279         for (int e = 0; e < exprs.length; e += 2) {
280             JexlExpression expr = jexl.createExpression(exprs[e]);
281             final Object expected = exprs[e + 1];
282             Object value = expr.evaluate(context);
283             assertEquals(expected, value);
284             expr = jexl.createExpression(expr.getParsedText());
285             value = expr.evaluate(context);
286             assertEquals(expected, value);
287         }
288     }
289 
290     @Test
291     void test108() throws Exception {
292         JexlScript expr;
293         Object value;
294         final JexlEngine jexl = new Engine();
295         expr = jexl.createScript("size([])");
296         value = expr.execute(null);
297         assertEquals(0, value);
298         expr = jexl.createScript(expr.getParsedText());
299         value = expr.execute(null);
300         assertEquals(0, value);
301 
302         expr = jexl.createScript("if (true) { [] } else { {:} }");
303         value = expr.execute(null);
304         assertTrue(value.getClass().isArray());
305         expr = jexl.createScript(expr.getParsedText());
306         value = expr.execute(null);
307         assertTrue(value.getClass().isArray());
308 
309         expr = jexl.createScript("size({:})");
310         value = expr.execute(null);
311         assertEquals(0, value);
312         expr = jexl.createScript(expr.getParsedText());
313         value = expr.execute(null);
314         assertEquals(0, value);
315 
316         expr = jexl.createScript("if (false) { [] } else { {:} }");
317         value = expr.execute(null);
318         assertInstanceOf(Map.class, value);
319         expr = jexl.createScript(expr.getParsedText());
320         value = expr.execute(null);
321         assertInstanceOf(Map.class, value);
322     }
323 
324     @Test
325     void test109() throws Exception {
326         final JexlEngine jexl = new Engine();
327         Object value;
328         final JexlContext context = new MapContext();
329         context.set("foo.bar", 40);
330         value = jexl.createExpression("foo.bar + 2").evaluate(context);
331         assertEquals(42, value);
332     }
333 
334     @Test
335     void test110() throws Exception {
336         final JexlEngine jexl = new Engine();
337         final String[] names = {"foo"};
338         Object value;
339         final JexlContext context = new MapContext();
340         value = jexl.createScript("foo + 2", names).execute(context, 40);
341         assertEquals(42, value);
342         context.set("frak.foo", -40);
343         value = jexl.createScript("frak.foo - 2", names).execute(context, 40);
344         assertEquals(-42, value);
345     }
346 
347     @Test
348     void test111() throws Exception {
349         final JexlEngine jexl = new Engine();
350         Object value;
351         final JexlContext context = new MapContext();
352         final String strExpr = "((x>0)?\"FirstValue=\"+(y-x):\"SecondValue=\"+x)";
353         final JexlExpression expr = jexl.createExpression(strExpr);
354 
355         context.set("x", 1);
356         context.set("y", 10);
357         value = expr.evaluate(context);
358         assertEquals("FirstValue=9", value);
359 
360         context.set("x", 1.0d);
361         context.set("y", 10.0d);
362         value = expr.evaluate(context);
363         assertEquals("FirstValue=9.0", value);
364 
365         context.set("x", 1);
366         context.set("y", 10.0d);
367         value = expr.evaluate(context);
368         assertEquals("FirstValue=9.0", value);
369 
370         context.set("x", 1.0d);
371         context.set("y", 10);
372         value = expr.evaluate(context);
373         assertEquals("FirstValue=9.0", value);
374 
375         context.set("x", -10);
376         context.set("y", 1);
377         value = expr.evaluate(context);
378         assertEquals("SecondValue=-10", value);
379 
380         context.set("x", -10.0d);
381         context.set("y", 1.0d);
382         value = expr.evaluate(context);
383         assertEquals("SecondValue=-10.0", value);
384 
385         context.set("x", -10);
386         context.set("y", 1.0d);
387         value = expr.evaluate(context);
388         assertEquals("SecondValue=-10", value);
389 
390         context.set("x", -10.0d);
391         context.set("y", 1);
392         value = expr.evaluate(context);
393         assertEquals("SecondValue=-10.0", value);
394     }
395 
396     @Test
397     void test112() throws Exception {
398         Object result;
399         final JexlEngine jexl = new Engine();
400         result = jexl.createScript(Integer.toString(Integer.MAX_VALUE)).execute(null);
401         assertEquals(Integer.MAX_VALUE, result);
402         result = jexl.createScript(Integer.toString(Integer.MIN_VALUE + 1)).execute(null);
403         assertEquals(Integer.MIN_VALUE + 1, result);
404         result = jexl.createScript(Integer.toString(Integer.MIN_VALUE)).execute(null);
405         assertEquals(Integer.MIN_VALUE, result);
406     }
407 
408     @Test
409     void test117() throws Exception {
410         final JexlEngine jexl = new Engine();
411         final JexlExpression e = jexl.createExpression("TIMESTAMP > 20100102000000");
412         final JexlContext ctx = new MapContext();
413         ctx.set("TIMESTAMP", Long.valueOf("20100103000000"));
414         final Object result = e.evaluate(ctx);
415         assertTrue((Boolean) result);
416     }
417 
418     @Test
419     void test125() throws Exception {
420         final JexlEngine jexl = new Engine();
421         final JexlExpression e = jexl.createExpression("method()");
422         final JexlContext jc = new Foo125Context(jexl, new Foo125());
423         assertEquals("OK", e.evaluate(jc));
424     }
425 
426 @Test
427     void test130a() throws Exception {
428         final String myName = "Test.Name";
429         final Object myValue = "Test.Value";
430 
431         final JexlEngine myJexlEngine = new Engine();
432         final MapContext myMapContext = new MapContext();
433         myMapContext.set(myName, myValue);
434 
435         final Object myObjectWithTernaryConditional = myJexlEngine.createScript(myName + "?:null").execute(myMapContext);
436         assertEquals(myValue, myObjectWithTernaryConditional);
437     }
438 
439     @Test
440     void test130b() throws Exception {
441         final String myName = "Test.Name";
442         final Object myValue = new Object() {
443             @Override
444             public String toString() {
445                 return "Test.Value";
446             }
447         };
448 
449         final JexlEngine myJexlEngine = new Engine();
450         final MapContext myMapContext = new MapContext();
451         myMapContext.set(myName, myValue);
452 
453         final Object myObjectWithTernaryConditional = myJexlEngine.createScript(myName + "?:null").execute(myMapContext);
454         assertEquals(myValue, myObjectWithTernaryConditional);
455     }
456 
457     @Test
458     void test135() throws Exception {
459         final JexlEngine jexl = new Engine();
460         final JexlContext jc = new MapContext();
461         JexlScript script;
462         Object result;
463         final Map<Integer, Object> foo = new HashMap<>();
464         foo.put(3, 42);
465         jc.set("state", foo);
466 
467         script = jexl.createScript("var y = state[3]; y");
468         result = script.execute(jc, foo);
469         assertEquals(42, result);
470 
471         jc.set("a", 3);
472         script = jexl.createScript("var y = state[a]; y");
473         result = script.execute(jc, foo);
474         assertEquals(42, result);
475 
476         jc.set("a", 2);
477         script = jexl.createScript("var y = state[a + 1]; y");
478         result = script.execute(jc, foo);
479         assertEquals(42, result);
480 
481         jc.set("a", 2);
482         jc.set("b", 1);
483         script = jexl.createScript("var y = state[a + b]; y");
484         result = script.execute(jc, foo);
485         assertEquals(42, result);
486 
487         script = jexl.createScript("var y = state[3]; y", "state");
488         result = script.execute(null, foo, 3);
489         assertEquals(42, result);
490 
491         script = jexl.createScript("var y = state[a]; y", "state", "a");
492         result = script.execute(null, foo, 3);
493         assertEquals(42, result);
494 
495         script = jexl.createScript("var y = state[a + 1]; y", "state", "a");
496         result = script.execute(null, foo, 2);
497         assertEquals(42, result);
498 
499         script = jexl.createScript("var y = state[a + b]; y", "state", "a", "b");
500         result = script.execute(null, foo, 2, 1);
501         assertEquals(42, result);
502     }
503 
504     @Test
505     void test136() throws Exception {
506         final JexlEngine jexl = new Engine();
507         final JexlContext jc = new MapContext();
508         JexlScript script;
509         JexlExpression expr;
510         Object result;
511 
512         script = jexl.createScript("var x = $TAB[idx]; return x;", "idx");
513         jc.set("fn01", script);
514 
515         script = jexl.createScript("$TAB = { 1:11, 2:22, 3:33}; IDX=2;");
516         script.execute(jc);
517 
518         expr = jexl.createExpression("fn01(IDX)");
519         result = expr.evaluate(jc);
520         assertEquals(22, result, "EXPR01 result");
521     }
522 
523     //    @Test
524 //    void test138() throws Exception {
525 //        MapContext ctxt = new MapContext();
526 //        ctxt.set("tz", java.util.TimeZone.class);
527 //        String source = ""
528 //                + "var currentDate = new('java.util.Date');"
529 //                +  "var gmt = tz.getTimeZone('GMT');"
530 //                +  "var cet = tz.getTimeZone('CET');"
531 //                +  "var calendarGMT = new('java.util.GregorianCalendar' , gmt);"
532 //                +  "var calendarCET = new('java.util.GregorianCalendar', cet);"
533 //                +  "var diff = calendarCET.getTime() - calendarGMT.getTime();"
534 //                + "return diff";
535 //
536 //        JexlEngine jexl = new Engine();
537 //        JexlScript script = jexl.createScript(source);
538 //        Object result = script.execute(ctxt);
539 //        assertNotNull(result);
540 //    }
541     @Test
542     void test143() throws Exception {
543         final JexlEngine jexl = new Engine();
544         final JexlContext jc = new MapContext();
545         JexlScript script;
546         Object result;
547 
548         script = jexl.createScript("var total = 10; total = (total - ((x < 3)? y : z)) / (total / 10); total", "x", "y", "z");
549         result = script.execute(jc, 2, 2, 1);
550         assertEquals(8, result);
551         script = jexl.createScript("var total = 10; total = (total - ((x < 3)? y : 1)) / (total / 10); total", "x", "y", "z");
552         result = script.execute(jc, 2, 2, 1);
553         assertEquals(8, result);
554     }
555 
556     @Test
557     void test144() throws Exception {
558         final JexlEngine jexl = new Engine();
559         final JexlContext jc = new MapContext();
560         final JexlScript script = jexl.createScript("var total = 10; total('tt')");
561         final JexlException.Method ambiguous = assertThrows(JexlException.Method.class, () -> script.execute(jc));
562         assertEquals("total", ambiguous.getMethod());
563     }
564 
565     @Test
566     void test144a() throws Exception {
567         final JexlEngine jexl = new Engine();
568         final JexlContext jc = new MapContext();
569         jc.set("quuxClass", Quux144.class);
570         final JexlExpression create = jexl.createExpression("quux = new(quuxClass)");
571         JexlExpression assignArray = jexl.createExpression("quux.arr = [ 'hello', 'world' ]");
572         final JexlExpression checkArray = jexl.createExpression("quux.arr");
573 
574         // test with a string
575         final Quux144 quux = (Quux144) create.evaluate(jc);
576         assertNotNull(quux, "quux is null");
577 
578         // test with a nonempty string array
579         Object o = assignArray.evaluate(jc);
580         assertEquals(String[].class, o.getClass(), "Result is not a string array");
581         o = checkArray.evaluate(jc);
582         assertEquals(Arrays.asList("hello", "world"), Arrays.asList((String[]) o));
583 
584         // test with a null array
585         assignArray = jexl.createExpression("quux.arr = null");
586         o = assignArray.evaluate(jc);
587         assertNull(o);
588         o = checkArray.evaluate(jc);
589         assertNull(o);
590 
591         // test with an empty array
592         assignArray = jexl.createExpression("quux.arr = [ ]");
593         o = assignArray.evaluate(jc);
594         assertNotNull(o);
595         o = checkArray.evaluate(jc);
596         assertEquals(Collections.emptyList(), Arrays.asList((String[]) o));
597         assertEquals(0, ((String[]) o).length, "The array size is not zero");
598 
599         // test with an empty array on the overloaded setter for different types.
600         // so, the assignment should fail with logging 'The ambiguous property, arr2, should have failed.'
601         final JexlExpression assignArray2 = jexl.createExpression("quux.arr2 = [ ]");
602         assertThrows(JexlException.Property.class, () -> assignArray2.evaluate(jc),
603                 "The arr2 property shouldn't be set due to its ambiguity (overloaded setters with different types).");
604         assertNull(quux.arr2, "The arr2 property value should remain as null, not an empty array.");
605     }
606 
607     @Test
608     void test147b() throws Exception {
609         final String[] scripts = {"var x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x.one", // results to 1
610             "x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x.one",// results to 1
611             "x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x['one']",//results to 1
612             "var x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x['one']"// result to null ?
613         };
614 
615         final JexlEngine jexl = new Engine();
616         final JexlContext jc = new MapContext();
617         for (final String s : scripts) {
618             final Object o = jexl.createScript(s).execute(jc);
619             assertEquals(1, o);
620         }
621     }
622 
623     @Test
624     void test147c() throws Exception {
625         final String[] scripts = {
626             "var x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x.one",
627             "x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x.one",
628             "x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x['one']",
629             "var x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x['one']"
630         };
631         final JexlEngine jexl = new Engine();
632         for (final String s : scripts) {
633             final JexlContext jc = new MapContext();
634             final Object o = jexl.createScript(s).execute(jc);
635             assertEquals(1, o);
636         }
637     }
638 
639     @Test
640     void test148a() throws Exception {
641         final JexlEngine jexl = new Engine();
642         final JexlContext jc = new MapContext();
643         jc.set("u", new Utils());
644 
645         String src = "u.asList(['foo', 'bar'])";
646         JexlScript e = jexl.createScript(src);
647         Object o = e.execute(jc);
648         assertInstanceOf(List.class, o);
649         assertEquals(Arrays.asList("foo", "bar"), o);
650 
651         src = "u.asList([1, 2])";
652         e = jexl.createScript(src);
653         o = e.execute(jc);
654         assertInstanceOf(List.class, o);
655         assertEquals(Arrays.asList(1, 2), o);
656     }
657 
658     @Test
659     void test155() throws Exception {
660         final JexlEngine jexlEngine = new Engine();
661         final JexlExpression jexlExpresssion = jexlEngine.createExpression("first.second.name");
662         final JexlContext jc = new MapContext();
663         jc.set("first.second.name", "RIGHT");
664         jc.set("name", "WRONG");
665         final Object value = jexlExpresssion.evaluate(jc);
666         assertEquals("RIGHT", value.toString());
667     }
668 
669     @Test
670     void test179() throws Exception {
671         final JexlContext jc = new MapContext();
672         final JexlEngine jexl = new JexlBuilder().create();
673         final String src = "x = new ('java.util.HashSet'); x.add(1); x";
674         final JexlScript e = jexl.createScript(src);
675         final Object o = e.execute(jc);
676         assertInstanceOf(Set.class, o);
677         assertTrue(((Set) o).contains(1));
678     }
679 
680     @Test
681     void test192() throws Exception {
682         final JexlContext jc = new MapContext();
683         jc.set("x.y.z", C192.class);
684         final JexlEngine jexl = new JexlBuilder().create();
685         JexlExpression js0 = jexl.createExpression("x.y.z.callme(t)");
686         jc.set("t", null);
687         assertNull(js0.evaluate(jc));
688         jc.set("t", 10);
689         assertEquals(42, js0.evaluate(jc));
690         jc.set("t", -10);
691         assertEquals(-42, js0.evaluate(jc));
692         jc.set("t", null);
693         assertNull(js0.evaluate(jc));
694         js0 = jexl.createExpression("x.y.z.kickme().callme(t)");
695         jc.set("t", null);
696         assertNull(js0.evaluate(jc));
697         jc.set("t", 10);
698         assertEquals(42, js0.evaluate(jc));
699         jc.set("t", -10);
700         assertEquals(-42, js0.evaluate(jc));
701         jc.set("t", null);
702         assertNull(js0.evaluate(jc));
703     }
704 
705     @Test
706     void test199() throws Exception {
707         final JexlContext jc = new MapContext();
708         final JexlEngine jexl = new JexlBuilder().arithmetic(new JexlArithmetic(false)).create();
709 
710         final JexlScript e = jexl.createScript("(x, y)->{ x + y }");
711         Object r = e.execute(jc, true, "EURT");
712         assertEquals("trueEURT", r);
713         r = e.execute(jc, "ELSAF", false);
714         assertEquals("ELSAFfalse", r);
715     }
716 
717     @Test
718     void test5115a() throws Exception {
719         final String str = "{\n"
720                 + "  var x = \"A comment\";\n"
721                 + "  var y = \"A comment\";\n"
722                 + "}";
723         final JexlEngine jexl = new Engine();
724         final JexlScript s = jexl.createScript(str);
725     }
726 
727     @Test
728     void test5115b() throws Exception {
729         final String str = "{\n"
730                 + "  var x = \"A comment\";\n"
731                 + "}";
732         final JexlEngine jexl = new Engine();
733         final JexlScript s = jexl.createScript(str);
734     }
735 
736     @Test
737     void test5115c() throws Exception {
738         final URL testUrl = new File(TESTA).toURI().toURL();
739         final JexlEngine jexl = new Engine();
740         final JexlScript s = jexl.createScript(testUrl);
741     }
742 
743     @Test
744     void testQuestion42() throws Exception {
745         final JexlEngine jexl = new JexlBuilder().arithmetic(new Arithmetic42()).create();
746         final JexlContext jc = new Question42();
747 
748         final String str0 = "(functionA('z') | functionB('b')) &  (functionC('c') |  functionD('d') ) ";
749         final JexlExpression expr0 = jexl.createExpression(str0);
750         final Object value0 = expr0.evaluate(jc);
751         assertEquals("BCD", value0);
752 
753         final String str1 = "(functionA('z') & functionB('b')) |  (functionC('c') &  functionD('d') ) ";
754         final JexlExpression expr1 = jexl.createExpression(str1);
755         final Object value1 = expr1.evaluate(jc);
756         assertEquals("CD", value1);
757     }
758 
759     @Test
760     void testRichContext() throws Exception {
761         final A105 a105 = new A105("foo", "bar");
762         final JexlEngine jexl = new Engine();
763         Object value;
764         final JexlContext context = new RichContext(jexl, a105);
765         value = jexl.createScript("uppercase(nameA + propA)").execute(context);
766         assertEquals("FOOBAR", value);
767     }
768 
769     @Test
770     void testScaleIssue() throws Exception {
771         final JexlEngine jexlX = new Engine();
772         final String expStr1 = "result == salary/month * work.percent/100.00";
773         final JexlExpression exp1 = jexlX.createExpression(expStr1);
774         final JexlEvalContext ctx = new JexlEvalContext();
775         final JexlOptions options = ctx.getEngineOptions();
776         ctx.set("result", new BigDecimal("9958.33"));
777         ctx.set("salary", new BigDecimal("119500.00"));
778         ctx.set("month", new BigDecimal("12.00"));
779         ctx.set("work.percent", new BigDecimal("100.00"));
780 
781         // will fail because default scale is 5
782         assertFalse((Boolean) exp1.evaluate(ctx));
783 
784         // will succeed with scale = 2
785         options.setMathScale(2);
786         assertTrue((Boolean) exp1.evaluate(ctx));
787     }
788 
789 }