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.apache.commons.jexl3.internal.Util.debuggerCheck;
20 import static org.apache.commons.jexl3.JexlTestCase.TEST_PERMS;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
24 import static org.junit.jupiter.api.Assertions.assertNotEquals;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertNull;
27 import static org.junit.jupiter.api.Assertions.assertThrows;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
29 import static org.junit.jupiter.api.Assertions.fail;
30
31 import java.io.StringReader;
32 import java.io.StringWriter;
33 import java.lang.reflect.Proxy;
34 import java.math.MathContext;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.LinkedHashMap;
41 import java.util.LinkedHashSet;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.concurrent.atomic.AtomicInteger;
45 import java.util.stream.Collectors;
46 import java.util.stream.Stream;
47
48 import org.apache.commons.jexl3.internal.Engine32;
49 import org.apache.commons.jexl3.internal.OptionsContext;
50 import org.apache.commons.jexl3.introspection.JexlSandbox;
51 import org.junit.jupiter.api.Assertions;
52 import org.junit.jupiter.api.Test;
53
54
55
56
57 class Issues300Test {
58 public static class Arithmetic383 extends JexlArithmetic {
59 public Arithmetic383(final boolean astrict) {
60 super(astrict);
61 }
62
63 @Override
64 public boolean isStrict(final JexlOperator op) {
65 switch (op) {
66 case NOT:
67 case CONDITION:
68 return false;
69 default: return super.isStrict(op);
70 }
71 }
72 }
73
74 public static class Arithmetic384 extends JexlArithmetic {
75 public Arithmetic384(final boolean astrict) {
76 super(astrict);
77 }
78
79 @Override
80 public boolean isStrict(final JexlOperator op) {
81 if (JexlOperator.ADD == op) {
82 return false;
83 }
84 return super.isStrict(op);
85 }
86 }
87
88 public static class Arithmetic384c extends JexlArithmetic {
89 AtomicInteger cmp = new AtomicInteger();
90
91 public Arithmetic384c(final boolean astrict) {
92 super(astrict);
93 }
94
95 public Arithmetic384c(final boolean astrict, final MathContext bigdContext, final int bigdScale) {
96 super(astrict, bigdContext, bigdScale);
97 }
98
99 @Override
100 protected int compare(final Object l, final Object r, final String op) {
101 cmp.incrementAndGet();
102 return super.compare(l, r, op);
103 }
104
105 int getCmpCalls() {
106 return cmp.get();
107 }
108 }
109
110 public static class Arithmetic384d extends Arithmetic384c {
111 public Arithmetic384d(final boolean astrict) {
112 super(astrict);
113 }
114
115 public Arithmetic384d(final boolean astrict, final MathContext bigdContext, final int bigdScale) {
116 super(astrict, bigdContext, bigdScale);
117 }
118 }
119
120 private static class Class397 implements Interface397i {
121 @Override
122 public String summary() {
123 return getClass().getName();
124 }
125 }
126
127 public static class Context0930 extends MapContext {
128
129
130
131
132
133
134
135
136 public Stream<?> filter(final Stream<?> stream, final JexlScript filter) {
137 return stream.filter(x -> Boolean.TRUE.equals(filter.execute(this, x)));
138 }
139 }
140
141
142
143
144 public static class Driver0930 {
145 private final String name;
146
147 Driver0930(final String n) {
148 name = n;
149 }
150
151 public String getAttributeName() {
152 return name;
153 }
154 }
155
156 public interface Interface397i {
157 String summary();
158 }
159
160 public static class Session322 {
161 public User322 getUser() {
162 return new User322();
163 }
164 }
165
166 public static class TestObject374 {
167 private String name;
168 private TestObject374 nested;
169
170 public String getName() {
171 return name;
172 }
173
174 public TestObject374 getNested() {
175 return nested;
176 }
177
178 public void setName(final String name) {
179 this.name = name;
180 }
181
182 public void setNested(final TestObject374 nested) {
183 this.nested = nested;
184 }
185 }
186
187 public enum Type375 {
188 DELIVERY_ADDRESS, DOMICILE
189 }
190
191 public static class User322 {
192 public String getName() {
193 return "user322";
194 }
195 }
196
197 public static class VaContext extends MapContext {
198 VaContext(final Map<String, Object> vars) {
199 super(vars);
200 }
201
202 public int cell(final List<?> l, final String... ms) {
203 return 42 + cell(ms);
204 }
205
206 public int cell(final String... ms) {
207 return ms.length;
208 }
209 }
210
211 public static class Var370 {
212 private String name;
213
214 public String getName() {
215 return name;
216 }
217
218 public void setName(final String s) {
219 name = s;
220 }
221 }
222
223 static JexlContext pragmaticContext() {
224 final JexlOptions opts = new JexlOptions();
225 opts.setFlags("-strict", "-cancellable", "-lexical", "-lexicalShade", "+safe", "+sharedInstance");
226 return new JexlTestCase.PragmaticContext(opts);
227 }
228
229 <T> T createProxy(final JexlEngine jexl, final Object o, final Class[] clazzz) {
230
231 return (T) Proxy.newProxyInstance(getClass().getClassLoader(), clazzz, (proxy, method, args) -> jexl.invokeMethod(o, method.getName(), args));
232 }
233
234 private Object run361a(final JexlEngine jexl) {
235 final String src = "()-> { ()-> { if (versionFile != null) { return 'foo'; } else { return 'bar'; }} }";
236 final JexlScript script = jexl.createScript(src);
237 final Object result = script.execute(null);
238 final JexlScript rs = (JexlScript) result;
239 return rs.execute(null);
240 }
241
242 private Object run361b(final JexlEngine jexl) {
243
244 final String src = "()-> { ()-> {" +
245 "var voa = vaf.value;\n" +
246 "if (voa != NaN && voa <= 0)" +
247 "{ return 'foo'; } else { return 'bar'; }" +
248 "} }";
249
250 final JexlContext context = new MapContext();
251 final Map<String, Object> vaf = Collections.singletonMap("value", null);
252 context.set("vaf", vaf);
253 final JexlScript script = jexl.createScript(src);
254 final Object result = script.execute(null);
255 final JexlScript rs = (JexlScript) result;
256 return rs.execute(context);
257 }
258
259 private String run361c(final JexlEngine jexl) {
260
261 final String src = "$$var t = null;\n" +
262 "$$if (t < 0) {\n" +
263 "'foo'\n" +
264 "$$} else {\n" +
265 "'bar'\n" +
266 "$$}";
267
268 final JxltEngine jxlt = jexl.createJxltEngine();
269 final JexlContext context = new MapContext();
270 final Map<String, Object> vaf = Collections.singletonMap("value", null);
271 context.set("vaf", vaf);
272 final JxltEngine.Template template = jxlt.createTemplate(src);
273 final StringWriter strw = new StringWriter();
274 template.evaluate(context, strw);
275 return strw.toString();
276 }
277
278 private Object run361d(final JexlEngine jexl) {
279 final String src = "var foo = 42; var foo = 43;";
280 final JexlScript script = jexl.createScript(src);
281 return script.execute(null);
282 }
283
284 @Test
285 void test301a() {
286 final JexlEngine jexl = new JexlBuilder().safe(false).arithmetic(new JexlArithmetic(false)).create();
287 final String[] srcs = { "var x = null; x.0", "var x = null; x[0]", "var x = [null,1]; x[0][0]" };
288 for (int i = 0; i < srcs.length; ++i) {
289 final String src = srcs[i];
290 final JexlScript s = jexl.createScript(src);
291 try {
292 final Object o = s.execute(null);
293 if (i > 0) {
294 fail(src + ": Should have failed");
295 }
296 } catch (final Exception ex) {
297 assertTrue(ex.getMessage().contains("x"));
298 }
299 }
300 }
301
302 @Test
303 void test302() {
304 final JexlContext jc = new MapContext();
305
306 final String[] strs = {
307 "{if (0) 1 else 2; var x = 4;}",
308 "if (0) 1; else 2; ",
309 "{ if (0) 1; else 2; }",
310 "{ if (0) { if (false) 1 else -3 } else 2; }"
311 };
312
313 final JexlEngine jexl = new JexlBuilder().create();
314 for (final String str : strs) {
315 final JexlScript e = jexl.createScript(str);
316 final Object o = e.execute(jc);
317 final int oo = ((Number) o).intValue() % 2;
318 assertEquals(0, oo, () -> "Block result is wrong " + str);
319 }
320 }
321
322 @Test
323 void test304() {
324 final JexlEngine jexlEngine = new JexlBuilder().strict(false).create();
325 JexlExpression e304 = jexlEngine.createExpression("overview.limit.var");
326
327 final Map<String, Object> map3 = new HashMap<>();
328 map3.put("var", "4711");
329 final Map<String, Object> map2 = new HashMap<>();
330 map2.put("limit", map3);
331 final Map<String, Object> map = new HashMap<>();
332 map.put("overview", map2);
333
334 final JexlContext context = new MapContext(map);
335 Object value = e304.evaluate(context);
336 assertEquals("4711", value);
337
338 map.clear();
339 map.put("overview.limit.var", 42);
340 value = e304.evaluate(context);
341 assertEquals(42, value);
342
343
344 final String[] keywords = {
345 "if", "else", "do", "while", "for", "break", "continue", "function", "return", "new", "size", "empty",
346 "var", "let", "const",
347 "null", "true", "false",
348 "not", "div", "mod", "and", "or",
349 "eq", "ne", "lt", "gt", "ge", "le",
350 };
351
352 for (final String keyword : keywords) {
353 final String pkw = "e304." + keyword;
354 map.put(pkw, 42);
355 e304 = jexlEngine.createExpression(pkw);
356 value = e304.evaluate(context);
357 assertEquals(42, value);
358 }
359 for (int i = 0; i < keywords.length; ++i) {
360 final String pkw = "e304." + keywords[i] + "." + keywords[keywords.length - 1 - i];
361 map.put(pkw, 42);
362 e304 = jexlEngine.createExpression(pkw);
363 value = e304.evaluate(context);
364 assertEquals(42, value);
365 }
366 final String allkw = "e304." + String.join(".", keywords);
367 map.put(allkw, 42);
368 e304 = jexlEngine.createExpression(allkw);
369 value = e304.evaluate(context);
370 assertEquals(42, value);
371 }
372
373 @Test
374 void test305() {
375 final JexlEngine jexl = new JexlBuilder().create();
376 JexlScript e;
377 e = jexl.createScript("{while(false) {}; var x = 1;}");
378 final String str0 = e.getParsedText();
379 e = jexl.createScript(str0);
380 assertNotNull(e);
381 final String str1 = e.getParsedText();
382 assertEquals(str0, str1);
383 }
384
385 @Test
386 void test306() {
387 final JexlContext ctxt = new MapContext();
388 final JexlEngine jexl = new JexlBuilder().create();
389 final JexlScript e = jexl.createScript("x.y ?: 2");
390 final Object o1 = e.execute(null);
391 assertEquals(2, o1);
392 ctxt.set("x.y", null);
393 final Object o2 = e.execute(ctxt);
394 assertEquals(2, o2);
395 }
396
397 @Test
398 void test306a() {
399 final JexlEngine jexl = new JexlBuilder().create();
400 final JexlScript e = jexl.createScript("x.y ?: 2", "x");
401 Object o = e.execute(null, new Object());
402 assertEquals(2, o);
403 o = e.execute(null);
404 assertEquals(2, o);
405 }
406
407 @Test
408 void test306b() {
409 final JexlEngine jexl = new JexlBuilder().create();
410 final JexlScript e = jexl.createScript("x?.y ?: 2", "x");
411 final Object o1 = e.execute(null, new Object());
412 assertEquals(2, o1);
413 final Object o2 = e.execute(null);
414 assertEquals(2, o2);
415 }
416
417 @Test
418 void test306c() {
419 final JexlEngine jexl = new JexlBuilder().safe(true).create();
420 final JexlScript e = jexl.createScript("x.y ?: 2", "x");
421 Object o = e.execute(null, new Object());
422 assertEquals(2, o);
423 o = e.execute(null);
424 assertEquals(2, o);
425 }
426
427 @Test
428 void test306d() {
429 final JexlEngine jexl = new JexlBuilder().safe(true).create();
430 final JexlScript e = jexl.createScript("x.y[z.t] ?: 2", "x");
431 Object o = e.execute(null, new Object());
432 assertEquals(2, o);
433 o = e.execute(null);
434 assertEquals(2, o);
435 }
436
437 @Test
438 void test309a() {
439
440 final String src = "<html lang=\"en\">\n"
441 + " <body>\n"
442 + " <h1>Hello World!</h1>\n"
443 + "$$ var i = 12++;\n"
444 + " </body>\n"
445 + "</html>";
446
447 final JexlEngine jexl = new JexlBuilder().safe(true).create();
448 final JxltEngine jxlt = jexl.createJxltEngine();
449 final JexlInfo info = new JexlInfo("template", 1, 1);
450 final JexlException.Parsing xerror = assertThrows(JexlException.Parsing.class, () -> jxlt.createTemplate(info, src));
451 assertEquals(4, xerror.getInfo().getLine());
452 }
453
454 @Test
455 void test309b() {
456
457 final String src = "<html lang=\"en\">\n"
458 + " <body>\n"
459 + " <h1>Hello World!</h1>\n"
460 + "$$ var i = a b c;\n"
461 + " </body>\n"
462 + "</html>";
463
464 final JexlEngine jexl = new JexlBuilder().safe(true).create();
465 final JxltEngine jxlt = jexl.createJxltEngine();
466 final JexlInfo info = new JexlInfo("template", 1, 1);
467 final JexlException.Parsing xerror = assertThrows(JexlException.Parsing.class, () -> jxlt.createTemplate(info, src));
468 assertEquals(4, xerror.getInfo().getLine());
469 }
470
471 @Test
472 void test309c() {
473
474 final String src = "<html lang=\"en\">\n"
475 + " <body>\n"
476 + " <h1>Hello World!</h1>\n"
477 + "$$ var i =12;\n"
478 + " </body>\n"
479 + "</html>";
480
481 final JexlEngine jexl = new JexlBuilder().safe(true).create();
482 final JxltEngine jxlt = jexl.createJxltEngine();
483 final JexlInfo info = new JexlInfo("template", 1, 1);
484 final JxltEngine.Template tmplt = jxlt.createTemplate(info, src);
485 final String src1 = tmplt.asString();
486 final String src2 = tmplt.toString();
487 assertEquals(src1, src2);
488 }
489
490 @Test
491 void test314() {
492 final JexlEngine jexl = new JexlBuilder().strict(true).safe(false).create();
493 final Map<String, Object> vars = new HashMap<>();
494 final JexlContext ctxt = new VaContext(vars);
495 JexlScript script;
496 Object result;
497 script = jexl.createScript("cell()");
498 result = script.execute(ctxt);
499 assertEquals(0, result);
500 script = jexl.createScript("x.cell()", "x");
501 result = script.execute(ctxt, Arrays.asList(10, 20));
502 assertEquals(42, result);
503 script = jexl.createScript("cell('1', '2')");
504 result = script.execute(ctxt);
505 assertEquals(2, result);
506 script = jexl.createScript("x.cell('1', '2')", "x");
507 result = script.execute(ctxt, Arrays.asList(10, 20));
508 assertEquals(44, result);
509
510 vars.put("TVALOGAR", null);
511 String jexlExp = "TVALOGAR==null ?'SIMON':'SIMONAZO'";
512 script = jexl.createScript(jexlExp);
513 result = script.execute(ctxt);
514 assertEquals("SIMON", result);
515
516 jexlExp = "TVALOGAR.PEPITO==null ?'SIMON':'SIMONAZO'";
517 script = jexl.createScript(jexlExp);
518
519 final Map<String, Object> tva = new LinkedHashMap<>();
520 tva.put("PEPITO", null);
521 vars.put("TVALOGAR", tva);
522 result = script.execute(ctxt);
523 assertEquals("SIMON", result);
524
525 vars.remove("TVALOGAR");
526 ctxt.set("TVALOGAR.PEPITO", null);
527 result = script.execute(ctxt);
528 assertEquals("SIMON", result);
529 }
530
531 @Test
532 void test315() {
533 final JexlEngine jexl = new JexlBuilder().strict(true).create();
534 final Map<String, Object> vars = new HashMap<>();
535 final JexlContext ctxt = new VaContext(vars);
536 JexlScript script;
537 Object result;
538 script = jexl.createScript("a?? 42 + 10", "a");
539 result = script.execute(ctxt, 32);
540 assertEquals(32, result);
541 result = script.execute(ctxt, (Object) null);
542 assertEquals(52, result);
543 script = jexl.createScript("- a??42 + +10", "a");
544 result = script.execute(ctxt, 32);
545 assertEquals(-32, result);
546 result = script.execute(ctxt, (Object) null);
547 assertEquals(52, result);
548
549 script = jexl.createScript("a? a : +42 + 10", "a");
550 result = script.execute(ctxt, 32);
551 assertEquals(32, result);
552 result = script.execute(ctxt, (Object) null);
553 assertEquals(52, result);
554
555 script = jexl.createScript("a ?: +42 + 10", "a");
556 result = script.execute(ctxt, 32);
557 assertEquals(32, result);
558 result = script.execute(ctxt, (Object) null);
559 assertEquals(52, result);
560 }
561
562 @Test
563 void test317() {
564 final JexlEngine jexl = new JexlBuilder().strict(true).create();
565 final JexlContext ctxt = new MapContext();
566 JexlScript script;
567 Object result;
568 JexlInfo info = new JexlInfo("test317", 1, 1);
569
570 script = jexl.createScript(info, "var f = "
571 + "()-> {x + x }; f",
572 "x");
573
574 result = script.execute(ctxt, 21);
575 assertInstanceOf(JexlScript.class, result);
576 script = (JexlScript) result;
577 info = JexlInfo.from(script);
578 assertNotNull(info);
579 assertEquals("test317", info.getName());
580 result = script.execute(ctxt, 21);
581 assertEquals(42, result);
582 }
583
584 @Test
585 void test322a() {
586 final JexlEngine jexl = new JexlBuilder().strict(true).create();
587 final JxltEngine jxlt = jexl.createJxltEngine();
588 final JexlContext context = new MapContext();
589
590 final String[] ins = { "${'{'}", "${\"{\"}", "${\"{}\"}", "${'{42}'}", "${\"{\\\"\\\"}\"}" };
591 final String[] ctls = { "{", "{", "{}", "{42}", "{\"\"}" };
592 StringWriter strw;
593 JxltEngine.Template template;
594 String output;
595
596 for (int i = 0; i < ins.length; ++i) {
597 final String src = ins[i];
598 template = jxlt.createTemplate("$$", new StringReader(src));
599 strw = new StringWriter();
600 template.evaluate(context, strw);
601 output = strw.toString();
602 assertEquals(ctls[i], output);
603 }
604 }
605
606 @Test
607 void test322b() {
608 final JexlContext ctxt = new MapContext();
609 final String src = "L'utilisateur ${session.user.name} s'est connecte";
610 final JexlEngine jexl = new JexlBuilder().strict(true).create();
611 final JxltEngine jxlt = jexl.createJxltEngine();
612 StringWriter strw;
613 JxltEngine.Template template;
614 String output;
615 template = jxlt.createTemplate("$$", new StringReader(src));
616
617 ctxt.set("session", new Session322());
618 strw = new StringWriter();
619 template.evaluate(ctxt, strw);
620 output = strw.toString();
621 assertEquals("L'utilisateur user322 s'est connecte", output);
622
623 ctxt.set("session.user", new User322());
624 strw = new StringWriter();
625 template.evaluate(ctxt, strw);
626 output = strw.toString();
627 assertEquals("L'utilisateur user322 s'est connecte", output);
628
629 ctxt.set("session.user.name", "user322");
630 strw = new StringWriter();
631 template.evaluate(ctxt, strw);
632 output = strw.toString();
633 assertEquals("L'utilisateur user322 s'est connecte", output);
634 }
635
636 @Test
637 void test323() {
638 final JexlEngine jexl = new JexlBuilder().safe(false).create();
639 final Map<String, Object> vars = new HashMap<>();
640 final JexlContext jc = new MapContext(vars);
641 Object result;
642
643
644 final JexlScript script0 = jexl.createScript("a.n.t.variable");
645 JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> script0.execute(jc), "a.n.t.variable is undefined.");
646 assertTrue(xvar.toString().contains("a.n.t"));
647
648
649 jc.set("a.n.t.variable", null);
650 final JexlScript script = jexl.createScript("a.n.t.variable");
651 result = script.execute(jc);
652 assertNull(result);
653
654
655 jc.set("a.n.t", null);
656 final JexlScript script1 = jexl.createScript("a.n.t[0].variable");
657 xvar = assertThrows(JexlException.Variable.class, () -> script1.execute(jc), "a.n.t is null.");
658 assertTrue(xvar.toString().contains("a.n.t"));
659
660
661 vars.remove("a.n.t");
662 final JexlScript script2 = jexl.createScript("a.n.t[0].variable");
663 xvar = assertThrows(JexlException.Variable.class, () -> script2.execute(jc), "a.n.t is undefined.");
664 assertTrue(xvar.toString().contains("a.n.t"));
665
666
667 final List<Object> inner = new ArrayList<>();
668 vars.put("a.n.t", inner);
669 final JexlScript script3 = jexl.createScript("a.n.t[0].variable");
670 JexlException.Property xprop = assertThrows(JexlException.Property.class, () -> script3.execute(jc), "a.n.t is null.");
671 assertTrue(xprop.toString().contains("0"));
672
673
674 inner.add(42);
675 final JexlScript script4 = jexl.createScript("a.n.t[0].variable");
676 xprop = assertThrows(JexlException.Property.class, () -> script4.execute(jc), "a.n.t is null.");
677 assertTrue(xprop.toString().contains("variable"));
678 }
679
680 @Test
681 void test324() {
682 final JexlEngine jexl = new JexlBuilder().create();
683 final String src42 = "new('java.lang.Integer', 42)";
684 final JexlExpression expr0 = jexl.createExpression(src42);
685 assertEquals(42, expr0.evaluate(null));
686 final String parsed = expr0.getParsedText();
687 assertEquals(src42, parsed);
688 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createExpression("new()"), "should not parse");
689 assertTrue(xparse.toString().contains(")"));
690 }
691
692 @Test
693 void test325() {
694 final JexlEngine jexl = new JexlBuilder().safe(false).create();
695 final Map<String, Object> map = new HashMap<String, Object>() {
696 private static final long serialVersionUID = 1L;
697
698 @Override
699 public Object get(final Object key) {
700 return super.get(key == null ? "" : key);
701 }
702
703 @Override
704 public Object put(final String key, final Object value) {
705 return super.put(key == null ? "" : key, value);
706 }
707 };
708 map.put("42", 42);
709 final JexlContext jc = new MapContext();
710 JexlScript script;
711 Object result;
712
713 script = jexl.createScript("map[null] = 42", "map");
714 result = script.execute(jc, map);
715 assertEquals(42, result);
716 script = jexl.createScript("map[key]", "map", "key");
717 result = script.execute(jc, map, null);
718 assertEquals(42, result);
719 result = script.execute(jc, map, "42");
720 assertEquals(42, result);
721 }
722
723 @Test
724 void test330() {
725 final JexlEngine jexl = new JexlBuilder().create();
726
727
728
729 final String longExpression = ""
730 +
731 "'THIS IS A VERY VERY VERY VERY VERY VERY VERY "
732 +
733 "VERY VERY LONG STRING CONCATENATION ' + VARIABLE ' <--- "
734 +
735 "error: missing + between VARIABLE and literal'";
736
737 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createExpression(longExpression),
738 "parsing malformed expression did not throw exception");
739 assertTrue(xparse.getMessage().contains("VARIABLE"));
740 }
741
742 @Test
743 void test331() {
744 final JexlEngine jexl = new JexlBuilder().create();
745 final JexlContext ctxt = new MapContext();
746 JexlScript script;
747 Object result;
748 script = jexl.createScript("a + '\\n' + b", "a", "b");
749 result = script.execute(ctxt, "hello", "world");
750 assertTrue(result.toString().contains("\n"));
751 }
752
753 @Test
754 void test347() {
755 final String src = "A.B == 5";
756 JexlEngine jexl = new JexlBuilder().safe(true).create();
757 final JexlScript script = jexl.createScript(src);
758 Object result = script.execute(null);
759
760 assertFalse((Boolean) result);
761
762 jexl = new JexlBuilder().strict(true).safe(false).create();
763 final JexlContext ctxt = new MapContext();
764 final JexlScript script1 = jexl.createScript(src);
765
766 assertThrows(JexlException.class, () -> script1.execute(ctxt));
767
768 ctxt.set("A", null);
769 assertThrows(JexlException.class, () -> script1.execute(ctxt), "should only succeed with safe navigation");
770
771 ctxt.set("A.B", null);
772 result = script1.execute(ctxt);
773 assertFalse((Boolean) result);
774 }
775
776 @Test
777 void test349() {
778 final String text = "(A ? C.D : E)";
779 final JexlEngine jexl = new JexlBuilder().safe(true).create();
780 final JexlExpression expr = jexl.createExpression(text);
781 Assertions.assertNotNull(expr);
782 final JexlScript script = jexl.createScript(text);
783 Assertions.assertNotNull(script);
784 }
785
786 @Test
787 void test361_33() {
788 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
789 assertThrows(JexlException.class, () -> run361c(jexl), "null arg should fail");
790 }
791
792 @Test
793 void test361a_32() {
794 final JexlEngine jexl = new Engine32(new JexlBuilder().safe(false));
795 final Object result = run361a(jexl);
796 assertNotNull(result);
797 }
798
799 @Test
800 void test361a_33() {
801 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
802 assertThrows(JexlException.class, () -> run361a(jexl), "null arg should fail");
803 }
804
805 @Test
806 void test361b_32() {
807 final JexlEngine jexl = new Engine32(new JexlBuilder().safe(false).strict(false));
808 final Object result = run361b(jexl);
809 assertNotNull(result);
810 }
811
812 @Test
813 void test361b_33() {
814 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
815 assertThrows(JexlException.class, () -> run361b(jexl), "null arg should fail");
816 }
817
818 @Test
819 void test361c_32() {
820 final JexlEngine jexl = new Engine32(new JexlBuilder().safe(false).strict(false));
821 final String result = run361c(jexl);
822 assertNotNull(result);
823 }
824
825 @Test
826 void test361d_32() {
827 final JexlEngine jexl = new Engine32(new JexlBuilder().lexical(false).lexicalShade(false).safe(false));
828 final Object result = run361d(jexl);
829 assertNotNull(result);
830 }
831
832 @Test
833 void test361d_33() {
834 final JexlEngine jexl = new JexlBuilder().lexical(true).lexicalShade(true).safe(false).strict(true).create();
835 assertThrows(JexlException.class, () -> run361d(jexl), "null arg should fail");
836 }
837
838 @Test
839 void test367() {
840 final String text = "var toto; function foo(x) { x }; var tata = 3; foo(3)";
841 final JexlEngine jexl = new JexlBuilder().safe(true).create();
842 final JexlScript script = jexl.createScript(text);
843 final Object result = script.execute(null);
844 assertEquals(3, result);
845 final String s0 = script.getParsedText();
846 final String s1 = script.getSourceText();
847 assertNotEquals(s0, s1);
848 }
849
850 @Test
851 void test370() {
852 final Var370 var370 = new Var370();
853 final JexlEngine jexl = new JexlBuilder().safe(true).create();
854 final ObjectContext<Var370> ctxt = new ObjectContext<>(jexl, var370);
855 final JexlExpression get = jexl.createExpression("name");
856
857 var370.setName("John");
858 assertEquals("John", get.evaluate(ctxt));
859 assertTrue(ctxt.has("name"));
860
861 var370.setName(null);
862 assertNull(get.evaluate(ctxt));
863 assertTrue(ctxt.has("name"));
864
865 final JexlExpression get1 = jexl.createExpression("phone");
866 assertFalse(ctxt.has("phone"));
867 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> get1.evaluate(ctxt), "phone should be undefined.");
868 assertEquals("phone", xvar.getVariable());
869 }
870
871 @Test
872 void test373b() {
873 final String src = "var i = ++1";
874 final JexlEngine jexl = new JexlBuilder().safe(true).create();
875 final JexlInfo info = new JexlInfo("badscript", 0, 0);
876 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(info, src), "should not parse");
877 assertTrue(xparse.getMessage().contains("badscript"));
878 }
879
880 @Test
881 void test374() {
882 final JexlEngine engine = new JexlBuilder().cache(512).strict(true).silent(false).antish(false).safe(false).create();
883
884 final JexlExpression expr = engine.createExpression("nested.name");
885
886 final TestObject374 myObject = new TestObject374();
887 myObject.setName("John");
888 final JexlContext context = new ObjectContext<>(engine, myObject);
889
890 assertThrows(JexlException.class, () -> expr.evaluate(context));
891 }
892
893 @Test
894 void test375() {
895 final JexlSandbox jexlSandbox = new JexlSandbox(false);
896 jexlSandbox.allow(Type375.class.getName());
897 final JexlEngine engine = new JexlBuilder().sandbox(jexlSandbox).create();
898
899 final JexlContext context = new MapContext();
900 context.set("Type", Type375.class);
901
902 Object result = engine.createScript("Type.valueOf('DOMICILE')").execute(context);
903 assertEquals(Type375.DOMICILE, result);
904
905 result = engine.createScript("Type.DOMICILE").execute(context);
906 assertEquals(Type375.DOMICILE, result);
907 }
908
909 @Test
910 void test377() {
911 final String text = "function add(x, y) { x + y } add(a, b)";
912 final JexlEngine jexl = new JexlBuilder().safe(true).create();
913 final JexlScript script = jexl.createScript(text, "a", "b");
914 final Object result = script.execute(null, 20, 22);
915 assertEquals(42, result);
916 }
917
918 @Test
919 void test379a() {
920
921 final String src =
922 "#pragma jexl.import java.util\n"+
923 "const map = new LinkedHashMap({0 : 'zero'});";
924
925 final JexlEngine jexl = new JexlBuilder().safe(true).create();
926 final JexlScript script = jexl.createScript(src);
927 assertNotNull(script);
928 final Object result = script.execute(null);
929 assertNotNull(result);
930 assertInstanceOf(LinkedHashMap.class, result);
931 assertEquals(1, ((Map) result).size());
932 }
933
934 @Test
935 void test383() {
936 final JexlEngine jexl = new JexlBuilder().safe(false).arithmetic(new Arithmetic383(true)).create();
937 final String src0 = "if (a) 1; else 2;";
938 final String src1 = "if (!a) 1; else 2;";
939
940 final JexlScript s0 = jexl.createScript(src0, "a");
941 final JexlScript s1 = jexl.createScript(src1, "a");
942 assertEquals(2, s0.execute(null, (Object) null));
943 assertEquals(1, s1.execute(null, (Object) null));
944
945 final JexlScript s2 = jexl.createScript(src0);
946 final JexlScript s3 = jexl.createScript(src1);
947 JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(null, (Object) null));
948 assertEquals("a", xvar.getVariable());
949 xvar = assertThrows(JexlException.Variable.class, () -> s3.execute(null, (Object) null));
950 assertEquals("a", xvar.getVariable());
951
952
953 final MapContext ctxt = new MapContext();
954 ctxt.set("a", null);
955 assertEquals(2, s2.execute(ctxt, (Object) null));
956 assertEquals(1, s3.execute(ctxt, (Object) null));
957 }
958
959 @Test
960 void test384a() {
961 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
962
963 for (final String src0 : Arrays.asList("'ABC' + null", "null + 'ABC'")) {
964 final JexlContext ctxt = new MapContext();
965 final JexlScript s0 = jexl.createScript(src0);
966 final JexlException xvar = assertThrows(JexlException.class, () -> s0.execute(ctxt, (Object) null), "null argument should throw");
967 assertTrue(xvar.toString().contains("+"));
968 }
969
970 for (final String src1 : Arrays.asList("'ABC' + a", "a + 'ABC'")) {
971 final JexlContext ctxt = new MapContext();
972 final JexlScript s1 = jexl.createScript(src1, "a");
973 JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> s1.execute(ctxt, (Object) null), "null argument should throw");
974 assertEquals("a", xvar.getVariable());
975
976 final JexlScript s2 = jexl.createScript(src1);
977 xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(ctxt, (Object) null), "null argument should throw");
978 assertEquals("a", xvar.getVariable());
979 assertTrue(xvar.isUndefined());
980
981 ctxt.set("a", null);
982 xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(ctxt, (Object) null), "null argument should throw");
983 assertEquals("a", xvar.getVariable());
984 assertFalse(xvar.isUndefined());
985 }
986 }
987
988 @Test
989 void test384b() {
990
991
992 final JexlEngine jexl = new JexlBuilder()
993 .arithmetic(new Arithmetic384(true))
994 .safe(false)
995 .strict(true)
996 .create();
997
998
999 for (final String src0 : Arrays.asList("'ABC' + null", "null + 'ABC'")) {
1000 final JexlContext ctxt = new MapContext();
1001 final JexlScript s0 = jexl.createScript(src0);
1002 assertEquals("ABC", s0.execute(ctxt));
1003 }
1004
1005 for (final String src1 : Arrays.asList("'ABC' + a", "a + 'ABC'")) {
1006 final JexlContext ctxt = new MapContext();
1007 final JexlScript s1 = jexl.createScript(src1, "a");
1008 assertEquals("ABC", s1.execute(ctxt, (Object) null));
1009
1010 final JexlScript s2 = jexl.createScript(src1);
1011 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(ctxt, (Object) null), "null argument should throw");
1012 assertEquals("a", xvar.getVariable());
1013 assertTrue(xvar.isUndefined());
1014
1015
1016 ctxt.set("a", null);
1017 assertEquals("ABC", s1.execute(ctxt, (Object) null));
1018 }
1019 }
1020
1021 @Test
1022 void test384c() {
1023 final Arithmetic384c ja = new Arithmetic384c(true);
1024
1025 final JexlEngine jexl = new JexlBuilder()
1026 .safe(false)
1027 .strict(true)
1028 .arithmetic(ja)
1029 .create();
1030
1031 assertTrue(ja.toBoolean(jexl.createExpression("3 < 4").evaluate(null)));
1032 assertTrue(ja.toBoolean(jexl.createExpression("6 <= 8").evaluate(null)));
1033 assertFalse(ja.toBoolean(jexl.createExpression("6 == 7").evaluate(null)));
1034 assertTrue(ja.toBoolean(jexl.createExpression("4 > 2").evaluate(null)));
1035 assertTrue(ja.toBoolean(jexl.createExpression("8 > 6").evaluate(null)));
1036 assertTrue(ja.toBoolean(jexl.createExpression("7 != 6").evaluate(null)));
1037 assertEquals(6, ja.getCmpCalls());
1038 }
1039
1040 @Test
1041 void test384d() {
1042 final Arithmetic384c ja = new Arithmetic384d(true);
1043
1044 final JexlEngine jexl = new JexlBuilder()
1045 .safe(false)
1046 .strict(true)
1047 .arithmetic(ja)
1048 .create();
1049
1050 assertTrue(ja.toBoolean(jexl.createExpression("3 < 4").evaluate(null)));
1051 assertTrue(ja.toBoolean(jexl.createExpression("6 <= 8").evaluate(null)));
1052 assertFalse(ja.toBoolean(jexl.createExpression("6 == 7").evaluate(null)));
1053 assertTrue(ja.toBoolean(jexl.createExpression("4 > 2").evaluate(null)));
1054 assertTrue(ja.toBoolean(jexl.createExpression("8 > 6").evaluate(null)));
1055 assertTrue(ja.toBoolean(jexl.createExpression("7 != 6").evaluate(null)));
1056 assertEquals(6, ja.getCmpCalls());
1057 }
1058
1059 @Test
1060 void test390() throws Exception {
1061
1062 final JexlEngine jexl = new JexlBuilder()
1063 .safe(false)
1064 .strict(true)
1065 .create();
1066
1067 JexlScript script = null;
1068 final String src = "if (true) #pragma one 42";
1069 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(src), "should have failed parsing");
1070 assertTrue(xparse.getDetail().contains("pragma"));
1071
1072 final String src1 = "if (true) { #pragma one 42 }";
1073 script = jexl.createScript(src1);
1074 final Object result = script.execute(null);
1075 debuggerCheck(jexl);
1076 }
1077
1078 @Test
1079 void test393() {
1080
1081 final String src = "const total = 0;\n" +
1082 "if (true) {\n" +
1083 " total = 1;\n" +
1084 "}\n" +
1085 "total; ";
1086 final JexlEngine jexl = new JexlBuilder()
1087 .safe(false)
1088 .strict(true)
1089 .create();
1090
1091 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(src), "should fail on const total assignment");
1092 assertTrue(xparse.getMessage().contains("total"));
1093 }
1094
1095 @Test
1096 void testBackslashes() {
1097 final JexlEngine jexl = new JexlBuilder().safe(false).create();
1098 final String src = "\"\b\t\f\"";
1099 JexlScript s = jexl.createScript(src);
1100 assertNotNull(s);
1101 final String ctl = "\b\t\f";
1102 assertEquals(ctl, s.execute(null));
1103 String parsed = s.getParsedText();
1104 assertEquals("'\\b\\t\\f'", parsed);
1105 s = jexl.createScript(src);
1106 assertNotNull(s);
1107 assertEquals(ctl, s.execute(null));
1108 parsed = s.getParsedText();
1109 assertEquals("'\\b\\t\\f'", parsed);
1110 }
1111
1112 @Test
1113 void testDow() {
1114
1115 final String src = "(y, m, d)->{\n" +
1116 "// will return 0 for Sunday, 6 for Saturday\n" +
1117 "const t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];\n"+
1118 "if (m < 3) { --y }\n" +
1119 "(y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;\n" +
1120 "}";
1121
1122 final JexlEngine jexl = new JexlBuilder().create();
1123 final JexlScript script = jexl.createScript(src);
1124 Object r = script.execute(null, 2023, 3, 1);
1125 assertInstanceOf(Number.class, r);
1126 Number dow = (Number) r;
1127 assertEquals(3, dow.intValue());
1128 r = script.execute(null, 1969, 7, 20);
1129 assertInstanceOf(Number.class, r);
1130 dow = (Number) r;
1131 assertEquals(0, dow.intValue());
1132 }
1133
1134 @Test
1135 void testIssue394() {
1136 final StringBuilder x = new StringBuilder("foobar");
1137 assertEquals("foobar", x.toString());
1138 final String src = "x -> x.setLength(3)";
1139 final JexlEngine jexl = new JexlBuilder().create();
1140 final JexlScript script = jexl.createScript(src);
1141 final Object result = script.execute(null, x);
1142 assertEquals("foo", x.toString());
1143 }
1144
1145 @Test
1146 void testIssue397() {
1147 String result;
1148 final String control = Class397.class.getName();
1149 final JexlEngine jexl = new JexlBuilder().permissions(TEST_PERMS).create();
1150
1151 final Interface397i instance = new Class397();
1152 result = (String) jexl.invokeMethod(instance, "summary");
1153 assertEquals(control, result);
1154
1155 final Interface397i proxy = createProxy(jexl, instance, new Class[] { Interface397i.class });
1156 result = (String) jexl.invokeMethod(proxy, "summary");
1157 assertEquals(control, result);
1158
1159 final JexlScript script = jexl.createScript("dan.summary()", "dan");
1160 result = (String) script.execute(null, instance);
1161 assertEquals(control, result);
1162 result = (String) script.execute(null, proxy);
1163 assertEquals(control, result);
1164 }
1165
1166 @Test
1167 void testIssue398a() {
1168
1169 final String src = "let m = {\n" +
1170 " \"foo\": 1,\n" +
1171 " \"bar\": 2,\n" +
1172 "}";
1173
1174 final JexlEngine jexl = new JexlBuilder().create();
1175 final JexlScript script = jexl.createScript(src);
1176 final Object result = script.execute(null);
1177 assertInstanceOf(Map.class, result);
1178 final Map<?, ?> map = (Map<?, ?>) result;
1179 assertEquals(2, map.size());
1180 }
1181
1182 @Test
1183 void testIssue398b() {
1184 final Map<String, Object> foo = Collections.singletonMap("X", "x");
1185 final Map<String, Object> bar = Collections.singletonMap("Y", "y");
1186 final JexlContext ctxt = new MapContext();
1187 ctxt.set("foo", foo);
1188 ctxt.set("bar", bar);
1189
1190 final String src = "let m = {\n" +
1191 " foo.X: 1,\n" +
1192 " bar.Y: 2,\n" +
1193 "}";
1194
1195 final JexlEngine jexl = new JexlBuilder().create();
1196 JexlScript script = jexl.createScript(src);
1197 Object result = script.execute(ctxt);
1198 assertInstanceOf(Map.class, result);
1199 Map<?, ?> map = (Map<?, ?>) result;
1200 assertEquals(2, map.size());
1201 assertEquals(1, map.get("x"));
1202 assertEquals(2, map.get("y"));
1203
1204 script = jexl.createScript(src, "foo", "bar");
1205 result = script.execute(null, foo, bar);
1206 assertInstanceOf(Map.class, result);
1207 map = (Map<?, ?>) result;
1208 assertEquals(2, map.size());
1209 assertEquals(1, map.get("x"));
1210 assertEquals(2, map.get("y"));
1211 }
1212
1213 @Test
1214 void testIssue398c() {
1215 final JexlEngine jexl = new JexlBuilder().create();
1216 final Object empty = jexl.createScript("[,...]").execute(null);
1217 assertNotNull(empty);
1218 assertTrue(jexl.createScript("[1]").execute(null) instanceof int[]);
1219 assertTrue(jexl.createScript("[1,...]").execute(null) instanceof ArrayList<?>);
1220 assertTrue(jexl.createScript("{1}").execute(null) instanceof HashSet<?>);
1221 assertTrue(jexl.createScript("{1,...}").execute(null) instanceof LinkedHashSet<?>);
1222 assertTrue(jexl.createScript("{'one': 1}").execute(null) instanceof HashMap<?, ?>);
1223 assertTrue(jexl.createScript("{'one': 1,...}").execute(null) instanceof LinkedHashMap<?, ?>);
1224 }
1225
1226 @Test
1227 void testPropagateOptions() {
1228
1229 final String src0 = "`${$options.strict?'+':'-'}strict"
1230 + " ${$options.cancellable?'+':'-'}cancellable"
1231 + " ${$options.lexical?'+':'-'}lexical"
1232 + " ${$options.lexicalShade?'+':'-'}lexicalShade"
1233 + " ${$options.sharedInstance?'+':'-'}sharedInstance"
1234 + " ${$options.safe?'+':'-'}safe`";
1235
1236 final String text = "#pragma script.mode pro50\n" + "()->{ ()->{ " + src0 + "; } }";
1237 final JexlEngine jexl = new JexlBuilder().safe(true).create();
1238 final JexlScript script = jexl.createScript(text);
1239 JexlContext context = pragmaticContext();
1240 final JexlScript closure = (JexlScript) script.execute(context);
1241 final JexlContext opts = new OptionsContext();
1242 final Object result = closure.execute(opts);
1243 assertEquals("+strict +cancellable +lexical +lexicalShade -sharedInstance -safe", result);
1244
1245 final String text0 = "#pragma script.mode pro50\n" + "()->{ " + src0 + "; }";
1246 final JexlScript script0 = jexl.createScript(text0);
1247 context = pragmaticContext();
1248 final Object result0 = script0.execute(context);
1249 assertEquals("+strict +cancellable +lexical +lexicalShade -sharedInstance -safe", result0);
1250
1251 final String text1 = "#pragma script.mode pro50\n" + src0;
1252 final JexlScript script1 = jexl.createScript(text1);
1253 context = pragmaticContext();
1254 final Object result1 = script1.execute(context);
1255 assertEquals("+strict +cancellable +lexical +lexicalShade -sharedInstance -safe", result1);
1256
1257 final String text2 = src0;
1258 final JexlScript script2 = jexl.createScript(text2);
1259 context = pragmaticContext();
1260 final Object result2 = script2.execute(context);
1261 assertEquals("-strict -cancellable -lexical -lexicalShade +sharedInstance +safe", result2);
1262 }
1263
1264 @Test
1265 void tests301b() {
1266 final JexlEngine jexl = new JexlBuilder().safe(false).arithmetic(new JexlArithmetic(false)).create();
1267 final Object[] xs = { null, null, new Object[] { null, 1 } };
1268 final String[] srcs = { "x.0", "x[0]", "x[0][0]" };
1269 final JexlContext ctxt = new MapContext();
1270 for (int i = 0; i < xs.length; ++i) {
1271 ctxt.set("x", xs[i]);
1272 final String src = srcs[i];
1273 final JexlScript s = jexl.createScript(src);
1274 assertThrows(JexlException.class, () -> s.execute(null));
1275 }
1276 }
1277
1278 @Test
1279 void testSO20220930() {
1280
1281 final List<Driver0930> values = new ArrayList<>();
1282 for (int i = 0; i < 8; ++i) {
1283 values.add(new Driver0930("drvr" + Integer.toOctalString(i)));
1284 }
1285 for (int i = 0; i < 4; ++i) {
1286 values.add(new Driver0930("favorite" + Integer.toOctalString(i)));
1287 }
1288
1289 final JexlEngine jexl = new JexlBuilder().safe(false).create();
1290 final JexlContext context = new Context0930();
1291 context.set("values", values);
1292 context.set("Collectors", Collectors.class);
1293
1294 final String src32 = "values.stream().filter((driver) ->{ driver.attributeName =^ 'favorite' }).collect(Collectors.toList())";
1295 final String src33 = "values.stream().filter(driver -> driver.attributeName =^ 'favorite').collect(Collectors.toList())";
1296 for (final String src : Arrays.asList(src32, src33)) {
1297 final JexlExpression s = jexl.createExpression(src);
1298 assertNotNull(s);
1299
1300 final Object r = s.evaluate(context);
1301 assertNotNull(r);
1302
1303 final List<Driver0930> l = (List<Driver0930>) r;
1304 assertEquals(4, l.size());
1305 for (final Driver0930 d : l) {
1306 assertTrue(d.getAttributeName().startsWith("favorite"));
1307 }
1308 }
1309 }
1310
1311 @Test
1312 void testUnsolvableMethod() {
1313 final JexlEngine jexl = new JexlBuilder().create();
1314
1315 final JexlScript script = jexl.createScript(
1316 "var myFunction1 = function(object) {"
1317 + " myNonExistentFunction();"
1318 + "}"
1319 + "var myFunction2 = function(object) {"
1320 + " myFunction1();"
1321 + "}"
1322 + "myFunction2();");
1323
1324 final JexlException.Method unsolvable = assertThrows(JexlException.Method.class, () -> script.execute(new MapContext()));
1325 assertEquals("myNonExistentFunction", unsolvable.getMethod());
1326 }
1327 }