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 static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
21 import static org.junit.jupiter.api.Assertions.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertNull;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.junit.jupiter.api.Assertions.fail;
26
27 import java.io.StringReader;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Deque;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.NoSuchElementException;
38 import java.util.Set;
39 import java.util.TreeSet;
40 import java.util.concurrent.ExecutorService;
41 import java.util.concurrent.Executors;
42
43 import org.apache.commons.jexl3.internal.TemplateDebugger;
44 import org.apache.commons.jexl3.introspection.JexlSandbox;
45 import org.apache.commons.logging.Log;
46 import org.junit.jupiter.api.BeforeEach;
47 import org.junit.jupiter.api.Test;
48
49
50
51
52 @SuppressWarnings({"boxing", "UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
53 class Issues200Test extends JexlTestCase {
54 public static class Arithmetic266 extends JexlArithmetic {
55 static final ThreadLocal<Deque<Iterator266>> TLS_FOREACH = new ThreadLocal<Deque<Iterator266>>() {
56 @Override
57 public Deque<Iterator266> initialValue() {
58 return new LinkedList<>();
59 }
60 };
61 static void closeIterator(final Iterator266 i266) {
62 final Deque<Iterator266> queue = TLS_FOREACH.get();
63 if (queue != null) {
64 queue.remove(i266);
65 }
66 }
67
68 public Arithmetic266(final boolean strict) {
69 super(strict);
70 }
71
72 public Iterator<?> forEach(final Iterable<?> collection) {
73 final Iterator266 it266 = new Iterator266((Iterator<Object>) collection.iterator());
74 final Deque<Iterator266> queue = TLS_FOREACH.get();
75 queue.addFirst(it266);
76 return it266;
77 }
78
79 public Iterator<?> forEach(final Map<?,?> collection) {
80 return forEach(collection.values());
81 }
82
83 public void remove() {
84 final Deque<Iterator266> queue = TLS_FOREACH.get();
85 final Iterator266 i266 = queue.getFirst();
86 if (i266 != null) {
87 i266.remove();
88 throw new JexlException.Continue(null);
89 }
90 throw new NoSuchElementException();
91 }
92 }
93
94 public static class Cls298 {
95 int sz = 42;
96
97 public boolean isEmpty() {
98 return sz <= 0;
99 }
100
101 public int size() {
102 return sz;
103 }
104
105 public int size(final int x) {
106 return sz + x;
107 }
108 }
109
110 public static class Context225 extends MapContext {
111 public String bar(){
112 return "bar";
113 }
114 }
115
116 public static class Context279 extends MapContext {
117 public Number identity(final Number x) {
118 return x;
119 }
120 public String identity(final String x) {
121 return x;
122 }
123 public String[] spread(final String str) {
124 if (str == null) {
125 return null;
126 }
127 final String[] a = new String[str.length()];
128 for(int i = 0; i < str.length(); ++i) {
129 a[i] = "" + str.charAt(i);
130 }
131 return a;
132 }
133 }
134
135 public static class Eval {
136 private JexlEngine jexl;
137
138 public JexlScript fn(final String src) {
139 return jexl.createScript(src);
140 }
141
142 void setJexl(final JexlEngine je) {
143 jexl = je;
144 }
145 }
146
147 public static class Foo245 {
148 private Object bar;
149
150 public Object getBar() {
151 return bar;
152 }
153
154 void setBar(final Object bar) {
155 this.bar = bar;
156 }
157 }
158
159
160
161
162 public static class Iterator266 implements Iterator<Object> {
163 private Iterator<Object> iterator;
164
165 Iterator266(final Iterator<Object> ator) {
166 iterator = ator;
167 }
168
169
170 public void close() {
171 if (iterator != null) {
172 Arithmetic266.closeIterator(this);
173 iterator = null;
174 }
175 }
176
177 @Override
178 protected void finalize() throws Throwable {
179 close();
180 super.finalize();
181 }
182
183 @Override
184 public boolean hasNext() {
185 if (iterator == null) {
186 return false;
187 }
188 final boolean n = iterator.hasNext();
189 if (!n) {
190 close();
191 }
192 return n;
193 }
194
195 @Override
196 public Object next() {
197 if (iterator == null) {
198 throw new NoSuchElementException();
199 }
200 return iterator.next();
201 }
202
203 @Override
204 public void remove() {
205 if (iterator != null) {
206 iterator.remove();
207 }
208 }
209 }
210
211 public static class JexlArithmetic224 extends JexlArithmetic {
212 public JexlArithmetic224(final boolean astrict) {
213 super(astrict);
214 }
215
216 public Object arrayGet(final Collection<?> c, final Number n) {
217 return nth(c, n.intValue());
218 }
219
220 public Object call(final Collection<?> c, final Number n) {
221 if (c instanceof List) {
222 return ((List<?>) c).get(n.intValue());
223 }
224 return nth(c, n.intValue());
225 }
226
227 protected Object nth(final Collection<?> c, int i) {
228 if (c instanceof List) {
229
230 return JexlEngine.TRY_FAILED;
231 }
232 for (final Object o : c) {
233 if (i-- == 0) {
234 return o;
235 }
236 }
237 return null;
238 }
239
240 public Object propertyGet(final Collection<?> c, final Number n) {
241 return nth(c, n.intValue());
242 }
243 }
244
245 public static class T210 {
246 public void npe() {
247 throw new NullPointerException("NPE210");
248 }
249 }
250
251 private static void handle(final ExecutorService pool, final JexlScript script, final Map<String, Object> payload) {
252 pool.submit(() -> script.execute(new MapContext(payload)));
253 }
254
255 public Issues200Test() {
256 super("Issues200Test", null);
257 }
258
259 @BeforeEach
260 @Override
261 public void setUp() {
262
263 java.util.logging.Logger.getLogger(JexlEngine.class.getName()).setLevel(java.util.logging.Level.SEVERE);
264 }
265
266 @Test
267 void test200() {
268 final JexlContext jc = new MapContext();
269 final Map<String, Object> funcs = new HashMap<>();
270 final Eval eval = new Eval();
271 funcs.put(null, eval);
272 final JexlEngine jexl = new JexlBuilder().namespaces(funcs).create();
273 eval.setJexl(jexl);
274 final String src = "var f = fn(\'(x)->{x + 42}\'); f(y)";
275 final JexlScript s200 = jexl.createScript(src, "y");
276 assertEquals(142, s200.execute(jc, 100));
277 assertEquals(52, s200.execute(jc, 10));
278 }
279
280 @Test
281 void test200b() {
282 final JexlContext jc = new MapContext();
283 final JexlEngine jexl = new JexlBuilder().create();
284 final JexlScript e = jexl.createScript("var x = 0; var f = (y)->{ x = y; }; f(42); x");
285 final Object r = e.execute(jc);
286 assertEquals(0, r);
287 }
288
289 @Test
290 void test209a() {
291 final JexlContext jc = new MapContext();
292 final JexlEngine jexl = new JexlBuilder().create();
293 final JexlScript e = jexl.createScript("var x = new('java.util.HashMap'); x.a = ()->{return 1}; x['a']()");
294 final Object r = e.execute(jc);
295 assertEquals(1, r);
296 }
297
298 @Test
299 void test209b() {
300 final JexlContext jc = new MapContext();
301 final JexlEngine jexl = new JexlBuilder().create();
302 final JexlScript e = jexl.createScript("var x = new('java.util.HashMap'); x['a'] = ()->{return 1}; x.a()");
303 final Object r = e.execute(jc);
304 assertEquals(1, r);
305 }
306
307 @Test
308 void test210() {
309 final JexlContext jc = new MapContext();
310 jc.set("v210", new T210());
311 final JexlEngine jexl = new JexlBuilder().strict(false).silent(false).create();
312 final JexlScript e = jexl.createScript("v210.npe()");
313 final JexlException xjexl = assertThrows(JexlException.class, () -> e.execute(jc));
314 final Throwable th = xjexl.getCause();
315 assertEquals("NPE210", th.getMessage());
316 }
317
318 @Test
319 void test217() {
320 final JexlEvalContext jc = new JexlEvalContext();
321 final JexlOptions options = jc.getEngineOptions();
322 jc.set("foo", new int[]{0, 1, 2, 42});
323 JexlEngine jexl;
324 JexlScript e;
325 Object r;
326 jexl = new JexlBuilder().strict(false).silent(false).create();
327 e = jexl.createScript("foo[3]");
328 r = e.execute(jc);
329 assertEquals(42, r);
330
331
332 jc.set("foo", new int[]{0, 1});
333 options.setStrict(true);
334 assertTrue(options.isStrict());
335 final JexlException xjexl = assertThrows(JexlException.class, () -> e.execute(jc));
336 assertEquals(ArrayIndexOutOfBoundsException.class, xjexl.getCause().getClass());
337
338 options.setStrict(false);
339 r = e.execute(jc);
340 assertNull(r, "oob adverted");
341 }
342
343 @Test
344 void test221() {
345 final JexlEvalContext jc = new JexlEvalContext();
346 final Map<String, Integer> map = new HashMap<>();
347 map.put("one", 1);
348 jc.set("map", map);
349 final JexlEngine jexl = new JexlBuilder().cache(256).create();
350 final JexlScript e = jexl.createScript("(x)->{ map[x] }");
351 Object r;
352 r = e.execute(jc, (Object) null);
353 assertNull(r);
354 r = e.execute(jc, (Object) null);
355 assertNull(r);
356 r = e.execute(jc, "one");
357 assertEquals(1, r);
358 }
359
360 @Test
361 void test224() {
362 final List<String> a0 = Arrays.asList("one", "two");
363 final Set<String> a1 = new TreeSet<>(a0);
364 final JexlContext jc = new MapContext();
365 final JexlEngine jexl = new JexlBuilder().arithmetic(new JexlArithmetic224(true)).create();
366 Object r;
367 JexlScript e = jexl.createScript("(map, x)->{ map[x] }");
368 r = e.execute(jc, a0, 1);
369 assertEquals("two", r);
370 r = e.execute(jc, a1, 1);
371 assertEquals("two", r);
372 e = jexl.createScript("(map)->{ map.1 }");
373 r = e.execute(jc, a0);
374 assertEquals("two", r);
375 r = e.execute(jc, a1);
376 assertEquals("two", r);
377 e = jexl.createScript("(map, x)->{ map(x) }");
378 r = e.execute(jc, a0, 1);
379 assertEquals("two", r);
380 r = e.execute(jc, a1, 1);
381 assertEquals("two", r);
382 }
383
384 @Test
385 void test225() {
386 final Context225 df = new Context225();
387 final JexlEngine jexl = new JexlBuilder().create();
388
389 final JexlExpression expression = jexl.createExpression("bar()");
390 assertEquals("bar", expression.evaluate(df));
391 final ObjectContext<Object> context = new ObjectContext<>(jexl, df);
392 assertEquals("bar", expression.evaluate(context));
393 }
394
395 @Test
396 void test230() {
397 final JexlEngine jexl = new JexlBuilder().cache(4).create();
398 final JexlContext ctxt = new MapContext();
399 final int[] foo = {42};
400 ctxt.set("fo o", foo);
401 Object value;
402 for (int l = 0; l < 2; ++l) {
403 value = jexl.createExpression("fo\\ o[0]").evaluate(ctxt);
404 assertEquals(42, value);
405 value = jexl.createExpression("fo\\ o[0] = 43").evaluate(ctxt);
406 assertEquals(43, value);
407 value = jexl.createExpression("fo\\ o.0").evaluate(ctxt);
408 assertEquals(43, value);
409 value = jexl.createExpression("fo\\ o.0 = 42").evaluate(ctxt);
410 assertEquals(42, value);
411 }
412 }
413
414 @Test
415 void test241() {
416 ExecutorService pool;
417 final JexlScript script = new JexlBuilder().create().createScript("`${item}`");
418
419 pool = Executors.newFixedThreadPool(4);
420
421 final Map<String, Object> m1 = new HashMap<>();
422 m1.put("item", "A");
423 final Map<String, Object> m2 = new HashMap<>();
424 m2.put("item", "B");
425
426 handle(pool, script, m1);
427 script.execute(new MapContext(m2));
428 pool.shutdown();
429 }
430
431 @Test
432 void test242() {
433 final Double a = -40.05d;
434 final Double b = -8.01d;
435 final Double c = a + b;
436 final JexlContext context = new MapContext();
437 context.set("a", a);
438 context.set("b", b);
439 final JexlEngine JEXL_ENGINE = new JexlBuilder().strict(true).silent(true).create();
440 final JexlExpression jsp = JEXL_ENGINE.createExpression("a + b");
441 final Double e = (Double) jsp.evaluate(context);
442 assertEquals(c, e, 0.0, () -> Double.doubleToLongBits(e) + " != " + Double.doubleToLongBits(c));
443 assertEquals(a + b, e, 0.0, () -> Double.doubleToLongBits(e) + " != " + Double.doubleToLongBits(c));
444 }
445
446 @Test
447 void test243a() {
448 final JexlEngine jexl = new JexlBuilder().cache(32).create();
449 final JexlScript script = jexl.createScript("while(true);");
450 assertThrows(JexlException.class, () -> jexl.createExpression("while(true);"), "expr do not allow 'while' statement");
451 }
452
453 @Test
454 void test245() {
455 final MapContext ctx = new MapContext();
456 final Foo245 foo245 = new Foo245();
457 ctx.set("foo", foo245);
458
459 final JexlEngine engine = new JexlBuilder().strict(true).safe(false).silent(false).create();
460 final JexlExpression foobar = engine.createExpression("foo.bar");
461 final JexlExpression foobaz = engine.createExpression("foo.baz");
462 final JexlExpression foobarbaz = engine.createExpression("foo.bar.baz");
463
464 final Object[] args = { null, 245 };
465 for (final Object arg : args) {
466 foo245.setBar(arg);
467
468 assertEquals(foo245.getBar(), foobar.evaluate(ctx));
469
470 assertThrows(JexlException.Property.class, () -> foobaz.evaluate(ctx), "foo.baz is not solvable, exception expected");
471
472 assertThrows(JexlException.Property.class, () -> foobarbaz.evaluate(ctx), "foo.bar.baz is not solvable, exception expected");
473 }
474 }
475
476 @Test
477 void test256() {
478 final MapContext ctx = new MapContext() {
479 @Override
480 public Object get(final String name) {
481 if ("java".equals(name)) {
482 return null;
483 }
484 return super.get(name);
485 }
486
487 @Override
488 public boolean has(final String name) {
489 if ("java".equals(name)) {
490 return false;
491 }
492 return super.has(name);
493 }
494
495 @Override
496 public void set(final String name, final Object value) {
497 if ("java".equals(name)) {
498 throw new JexlException(null, "cannot set " + name);
499 }
500 super.set(name, value);
501 }
502 };
503 ctx.set("java.version", 10);
504 final JexlEngine engine = new JexlBuilder().strict(true).silent(false).create();
505 final JexlScript script = engine.createScript("java = 3");
506 assertThrows(JexlException.class, () -> script.execute(ctx));
507 assertEquals(10, engine.createScript("java.version").execute(ctx));
508 }
509
510 @Test
511 void test265() {
512 final JexlEngine jexl = new JexlBuilder().cache(4).create();
513 final JexlContext ctxt = new MapContext();
514 ctxt.set("x", 42);
515 Object result;
516 JexlScript script;
517 assertThrows(JexlException.Parsing.class, () -> jexl.createScript("(true) ? x : abs(1)"), "ambiguous, parsing should fail");
518 script = jexl.createScript("(true) ? (x) : abs(2)");
519 result = script.execute(ctxt);
520 assertEquals(42, result);
521 script = jexl.createScript("(true) ? x : (abs(3))");
522 result = script.execute(ctxt);
523 assertEquals(42, result);
524 script = jexl.createScript("(!true) ? abs(4) : x");
525 result = script.execute(ctxt);
526 assertEquals(42, result);
527 }
528
529 @Test
530 void test266() {
531 Object result;
532 JexlScript script;
533 final JexlEngine jexl = new JexlBuilder().arithmetic(new Arithmetic266(true)).create();
534 final JexlContext ctxt = new MapContext();
535
536 final List<Integer> li = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5 ,6));
537 ctxt.set("list", li);
538 script = jexl.createScript("for (var item : list) { if (item <= 3) remove(); } return size(list)");
539 result = script.execute(ctxt);
540 assertEquals(3, result);
541 assertEquals(3, li.size());
542
543 final Map<String, Integer> msi = new HashMap<>();
544 msi.put("a", 1);
545 msi.put("b", 2);
546 msi.put("c", 3);
547 msi.put("d", 4);
548 msi.put("e", 5);
549 msi.put("f", 6);
550 ctxt.set("map", msi);
551 script = jexl.createScript("for (var item : map) { if (item <= 2) remove(); } return size(map)");
552 result = script.execute(ctxt);
553 assertEquals(4, result);
554 assertEquals(4, msi.size());
555 }
556
557 @Test
558 void test267() {
559 Object result;
560 JexlScript script;
561 final JexlEngine jexl = new JexlBuilder().create();
562 final JexlContext ctxt = new MapContext();
563
564 script = jexl.createScript("x + y", "x", "y");
565 result = script.execute(ctxt, 20, 22);
566 assertEquals(42, result);
567
568 script = jexl.createScript("(x, y)->{ x + y}");
569 result = script.execute(ctxt, 22, 20);
570 assertEquals(42, result);
571
572 script = jexl.createScript("return (x, y)->{ x + y}");
573 result = script.execute(ctxt);
574 assertInstanceOf(JexlScript.class, result);
575 }
576
577 @Test
578 void test274() {
579 JexlEngine jexl = new JexlBuilder().strict(true).safe(true).stackOverflow(5).create();
580 final JexlContext ctxt = new MapContext();
581 final JexlScript script = jexl.createScript("var f = (x)->{ x > 1? x * f(x - 1) : x }; f(a)", "a");
582 final Object result = script.execute(ctxt, 3);
583 assertEquals(6, result);
584 JexlException.StackOverflow xstack = assertThrows(JexlException.StackOverflow.class, () -> script.execute(ctxt, 32));
585 assertTrue(xstack.toString().contains("jexl"));
586 jexl = new JexlBuilder().strict(true).create();
587 final JexlScript script2 = jexl.createScript("var f = (x)->{ x * f(x - 1) }; f(a)", "a");
588 xstack = assertThrows(JexlException.StackOverflow.class, () -> script2.execute(ctxt, 32));
589 assertTrue(xstack.toString().contains("jvm"));
590 }
591
592 @Test
593 void test275a() {
594 final JexlContext ctxt = new MapContext();
595 ctxt.set("out", System.out);
596 final JexlEngine jexl = new JexlBuilder().strict(true).safe(true).create();
597 final JexlScript e = jexl.createScript("out.println(xyz)");
598 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> e.execute(ctxt));
599 assertEquals("xyz", xvar.getVariable());
600 }
601
602 @Test
603 void test275b() {
604 final JexlContext ctxt = new MapContext();
605
606 final JexlEngine jexl = new JexlBuilder().strict(true).safe(true).create();
607 final JexlScript e = jexl.createScript("var xyz = xyz");
608 final Object o = e.execute(ctxt);
609 assertNull(o);
610 }
611
612 @Test
613 void test275c() {
614 final JexlContext ctxt = new MapContext();
615
616 final JexlEngine jexl = new JexlBuilder().strict(true).safe(true).silent(true).create();
617 JexlScript e;
618 Object r;
619 e = jexl.createScript("(s, v)->{ var x = y ; 42; }");
620
621 r = e.execute(ctxt, false, true);
622 assertEquals(42, r);
623 }
624
625 @Test
626 void test275d() {
627 final JexlContext ctxt = new MapContext();
628 ctxt.set("out", System.out);
629 final JexlEngine jexl = new JexlBuilder().strict(true).safe(true).create();
630 final JexlScript e = jexl.createScript("{ var xyz = 42 } out.println(xyz)");
631 final Object o = e.execute(ctxt);
632 assertNull(o);
633 }
634
635 @Test
636 void test278() {
637
638 final String[] srcs = {
639 "return union x143('arg',5,6) ",
640 "return union y143('arg',5,6) ;",
641 "return union\n z143('arg',5,6) ;",
642 "var f =()->{ return union 143 } foo[0]"
643 };
644 final Object[] ctls = {
645 "42","42","42", 42
646 };
647
648 final JexlEngine jexl = new JexlBuilder().cache(4).create();
649 final JexlContext ctxt = new MapContext();
650 final int[] foo = { 42 };
651 ctxt.set("foo", foo);
652 ctxt.set("union", "42");
653 Object value;
654 JexlScript jc;
655 for (int i = 0; i < srcs.length; ++i) {
656 final String src = srcs[i];
657 final JexlException.Ambiguous xa = assertThrows(JexlException.Ambiguous.class, () -> jexl.createScript(src), src);
658 final String str = xa.toString();
659 assertTrue(str.contains("143"));
660 final String clean = xa.tryCleanSource(src);
661
662 jc = jexl.createScript(clean);
663 value = jc.execute(ctxt);
664 assertEquals(ctls[i], value, clean);
665 }
666 }
667
668 @Test
669 void test279() {
670 final Log logger = null;
671 Object result;
672 JexlScript script;
673 final JexlContext ctxt = new Context279();
674
675 final String[] srcs = {
676 "var z = null; identity(z[0]);",
677 "var z = null; z.0;",
678 "var z = null; z.foo();",
679 "z['y']['z']",
680 "z.y.any()",
681 "identity(z.any())",
682 "z[0]",
683 "z.0",
684 "z.foo()",
685 "z.y[0]",
686 "z.y[0].foo()",
687 "z.y.0",
688 "z.y.foo()",
689 "var z = { 'y' : [42] }; z.y[1]",
690 "var z = { 'y' : [42] }; z.y.1",
691 "var z = { 'y' : [-42] }; z.y[1].foo()",
692 "var z = { 'y' : [42] }; z.y.1.foo()",
693 "var z = { 'y' : [null, null] }; z.y[1].foo()",
694 "var z = { 'y' : [null, null] }; z.y.1.foo()"
695 };
696
697 for (int i = 0; i < 2; ++i) {
698 for (final boolean strict : new boolean[] { true, false }) {
699 final JexlEngine jexl = new JexlBuilder().safe(false).strict(strict).create();
700 for (final String src : srcs) {
701 script = jexl.createScript(src);
702 try {
703 result = script.execute(ctxt);
704 if (strict) {
705 if (logger != null) {
706 logger.warn(ctxt.has("z") + ": " + src + ": no fail, " + result);
707 }
708 fail("should have failed: " + src);
709 }
710
711 assertNull(result, "non-null result ?!");
712 } catch (final JexlException.Variable xvar) {
713 if (logger != null) {
714 logger.warn(ctxt.has("z") + ": " + src + ": fail, " + xvar);
715 }
716 if (!strict) {
717 fail(src + ", should not have thrown " + xvar);
718 } else {
719 assertTrue(xvar.toString().contains("z"), () -> src + ": " + xvar.toString());
720 }
721 } catch (final JexlException.Property xprop) {
722 if (logger != null) {
723 logger.warn(ctxt.has("z") + ": " + src + ": fail, " + xprop);
724 }
725 if (!strict) {
726 fail(src + ", should not have thrown " + xprop);
727 } else {
728 assertTrue(xprop.toString().contains("1"), () -> src + ": " + xprop.toString());
729 }
730 }
731 }
732 }
733 ctxt.set("z.y", null);
734 }
735 }
736
737 @Test
738 void test279b() {
739 Object result;
740 JexlScript script;
741 final JexlContext ctxt = new Context279();
742 ctxt.set("ctxt", ctxt);
743 final String src = "(x)->{ spread(x)[0].toString() }";
744 final JexlEngine jexl = new JexlBuilder().safe(true).strict(true).create();
745 script = jexl.createScript(src);
746 result = script.execute(ctxt, "abc");
747 assertEquals("a", result);
748 result = script.execute(ctxt, (Object) null);
749 assertNull(result);
750 }
751
752 @Test
753 void test285() {
754 final List<String> out = new ArrayList<>(6);
755 final JexlContext ctxt = new MapContext();
756 ctxt.set("$out", out);
757
758 final String src = "for(var b: ['g','h','i']) {\n"
759 + " var c = b;\n"
760 + " $out.add(c);\n"
761 + "}\n"
762 + " \n"
763 + "for(var dc: ['j','k','l']) {\n"
764 + " $out.add(dc);\n"
765 + "}"
766 + " \n"
767 + "$out.size()";
768
769 final JexlFeatures features = new JexlFeatures();
770 features.lexical(true);
771 final JexlEngine jexl = new JexlBuilder()
772
773 .safe(false).strict(true).lexical(true).create();
774 final JexlScript script = jexl.createScript(src);
775 final Object result = script.execute(ctxt, (Object) null);
776 assertEquals(6, result);
777 final List<String> ctl = Arrays.asList("g", "h", "i", "j", "k", "l");
778 assertEquals(ctl, out);
779 }
780
781 @Test
782 void test285a() {
783 final List<String> out = new ArrayList<>(6);
784 final JexlContext ctxt = new MapContext();
785 ctxt.set("$out", out);
786 final String src =
787 "for(var b: ['g','h','i']) { $out.add(b); }\n"
788 + "for(b: ['j','k','l']) { $out.add(b);}\n"
789 + "$out.size()";
790
791 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).lexical(false).create();
792 final JexlScript script = jexl.createScript(src);
793 final Object result = script.execute(ctxt, (Object) null);
794 assertEquals(6, result);
795 final List<String> ctl = Arrays.asList("g", "h", "i", "j", "k", "l");
796 assertEquals(ctl, out);
797 }
798
799 @Test
800 void test285b() {
801 final List<String> out = new ArrayList<>(6);
802 final JexlContext ctxt = new MapContext();
803 ctxt.set("$out", out);
804 final String src =
805 "for(b: ['g','h','i']) { $out.add(b); }\n"
806 + "for(var b: ['j','k','l']) { $out.add(b);}\n"
807 + "$out.size()";
808
809 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
810 final JexlScript script = jexl.createScript(src);
811 final Object result = script.execute(ctxt, (Object) null);
812 assertEquals(6, result);
813 final List<String> ctl = Arrays.asList("g", "h", "i", "j", "k", "l");
814 assertEquals(ctl, out);
815 }
816
817 @Test
818 void test286() {
819 final String s286 = "var x = 0; for(x : 1..2){}; return x";
820 final JexlEngine jexl = new JexlBuilder().strict(true).create();
821 assertEquals(2, jexl.createScript(s286).execute(null));
822 }
823
824 @Test
825 void test287() {
826 final JexlEvalContext ctxt = new JexlEvalContext();
827 final JexlOptions options = ctxt.getEngineOptions();
828 final JexlEngine jexl = new JexlBuilder().strict(true).create();
829 String src;
830 JexlScript script;
831 Object result;
832
833 src = "x = 1; if (false) var x = 2; x";
834 script = jexl.createScript(src);
835 result = script.execute(ctxt);
836 assertEquals(1, result);
837
838 src = "x = 1; if (true) var x = 2; x";
839 script = jexl.createScript(src);
840 result = script.execute(ctxt);
841 assertEquals(2, result);
842
843 src = "x = 1; var x = x + 41; x";
844 script = jexl.createScript(src);
845 result = script.execute(ctxt);
846 assertEquals(42, result);
847
848 options.setLexical(false);
849 src = "(x)->{ if (x==1) { var y = 2; } else if (x==2) { var y = 3; }; y }";
850 final JexlScript script1 = jexl.createScript(src);
851 result = script1.execute(ctxt, 1);
852 assertEquals(2, result);
853 result = script1.execute(ctxt, 2);
854 assertEquals(3, result);
855 options.setStrict(true);
856 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> script1.execute(ctxt, 0));
857 assertTrue(xvar.getMessage().contains("y"));
858 options.setStrict(false);
859 result = script1.execute(ctxt, 0);
860 assertNull(result);
861 }
862
863 @Test
864 void test289() {
865 final JexlContext ctxt = new MapContext();
866 final JexlEngine jexl = new JexlBuilder().strict(true).create();
867 String src;
868 JexlScript script;
869 Object result;
870 src = "var x = function(a) { var b; return b}; x(1,2)";
871 script = jexl.createScript(src);
872 result = script.execute(ctxt);
873 assertNull(result);
874 }
875
876 @Test
877 void test290a() {
878 Object result;
879 JexlScript script;
880 final String[] srcs = {
881 "(x)->{ x.nothing().toString() }",
882 "(x)->{ x.toString().nothing() }",
883 "(x)->{ x.nothing().nothing() }",
884 };
885 for (final boolean safe : new boolean[]{true, false}) {
886 final JexlEngine jexl = new JexlBuilder().safe(safe).strict(true).create();
887 for (final String src : srcs) {
888 script = jexl.createScript(src);
889 try {
890 result = script.execute(null, "abc");
891 if (!safe) {
892 fail("should have failed: " + src);
893 } else {
894 assertNull(result, "non-null result ?!");
895 }
896 } catch (final JexlException.Method xmethod) {
897 if (safe) {
898 fail(src + ", should not have thrown " + xmethod);
899 } else {
900 assertTrue(xmethod.toString().contains("nothing"), () -> src + ": " + xmethod.toString());
901 }
902 }
903 }
904 }
905 }
906
907 @Test
908 void test290b() {
909 Object result;
910 JexlScript script;
911 final String[] srcs = {
912 "(x)->{ x?.nothing()?.toString() }",
913 "(x)->{ x.toString()?.nothing() }",
914 "(x)->{ x?.nothing().nothing() }",};
915 final JexlEngine jexl = new JexlBuilder().strict(true).create();
916 for (final String src : srcs) {
917 script = jexl.createScript(src);
918 result = script.execute(null, "abc");
919 assertNull(result);
920 }
921 }
922
923 @Test
924 void test291() {
925 final String str = "{1:'one'}[1]";
926 final JexlContext ctxt = new MapContext();
927 final JexlEngine jexl = new JexlBuilder().create();
928 JexlExpression e = jexl.createExpression(str);
929 Object value = e.evaluate(ctxt);
930 assertEquals("one", value);
931
932 final JexlEngine sandboxedJexlEngine = new JexlBuilder().
933 sandbox(new JexlSandbox(true)).
934 create();
935 e = sandboxedJexlEngine.createExpression(str);
936 value = e.evaluate(ctxt);
937 assertEquals("one", value);
938 }
939
940 @Test
941 void test298() {
942 final Cls298 c298 = new Cls298();
943 final JexlContext ctxt = new MapContext();
944 final JexlEngine jexl = new JexlBuilder().create();
945
946 String str = "c.size()";
947 JexlScript e = jexl.createScript(str, "c");
948 Object value = e.execute(ctxt, c298);
949 assertEquals(42, value, str);
950
951 str = "size c";
952 e = jexl.createScript(str, "c");
953 value = e.execute(ctxt, c298);
954 assertEquals(42, value, str);
955
956 str = "c.size(127)";
957 e = jexl.createScript(str, "c");
958 value = e.execute(ctxt, c298);
959 assertEquals(169, value, str);
960 }
961
962 @Test
963 void testTemplate6565a() {
964 final JexlEngine jexl = new JexlBuilder().create();
965 final JxltEngine jexlt = jexl.createJxltEngine();
966 final String source =
967 "$$ var res = '';\n" +
968 "$$ var meta = session.data['METADATA'];\n" +
969 "$$ if (meta) {\n" +
970 "$$ var entry = meta['ID'];\n" +
971 "$$ if (entry) {\n" +
972 "$$ var value = session.data[entry];\n" +
973 "$$ res = value?: '';\n" +
974 "$$ }\n" +
975 "$$ }\n" +
976 "${res}\n";
977 final JxltEngine.Template script = jexlt.createTemplate("$$", new StringReader(source));
978 assertNotNull(script);
979 final TemplateDebugger dbg = new TemplateDebugger();
980 final String refactored = dbg.debug(script) ? dbg.toString() : "";
981 assertNotNull(refactored);
982 assertEquals(source, refactored);
983 }
984
985 @Test
986 void testTemplate6565b() {
987 final JexlEngine jexl = new JexlBuilder().create();
988 final JxltEngine jexlt = jexl.createJxltEngine();
989 final String source =
990 "$$ var res = '';\n" +
991 "$$ var meta = session.data['METADATA'];\n" +
992 "$$ if (meta) {\n" +
993 "$$ var entry = meta['ID'];\n" +
994 "$$ if (entry) {\n" +
995 "$$ var value = session.data[entry];\n" +
996 "$$ res = value?: '';\n" +
997 "${res}\n" +
998 "$$ }\n" +
999 "$$ }\n";
1000 final JxltEngine.Template script = jexlt.createTemplate("$$", new StringReader(source));
1001 assertNotNull(script);
1002 final TemplateDebugger dbg = new TemplateDebugger();
1003 final String refactored = dbg.debug(script) ? dbg.toString() : "";
1004 assertNotNull(refactored);
1005 assertEquals(source, refactored);
1006 }
1007 }