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 java.util.HashMap;
20 import java.util.Map;
21 import org.apache.commons.jexl3.junit.Asserter;
22 import java.util.Arrays;
23 import java.util.Date;
24 import org.apache.commons.jexl3.introspection.JexlMethod;
25 import org.apache.commons.jexl3.introspection.JexlPropertyGet;
26 import org.apache.commons.jexl3.introspection.JexlPropertySet;
27 import org.apache.commons.jexl3.introspection.JexlUberspect;
28 import org.junit.Assert;
29 import org.junit.Before;
30 import org.junit.Test;
31
32
33
34
35
36
37 @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
38 public class MethodTest extends JexlTestCase {
39 private Asserter asserter;
40 private static final String METHOD_STRING = "Method string";
41
42 public MethodTest() {
43 super("MethodTest");
44 }
45
46 public static class VarArgs {
47 public String callInts() {
48 final int result = -5000;
49 return "Varargs:" + result;
50 }
51
52 public String callInts(final Integer... args) {
53 int result = 0;
54 if (args != null) {
55 for (final Integer arg : args) {
56 result += arg != null ? arg : -100;
57 }
58 } else {
59 result = -1000;
60 }
61 return "Varargs:" + result;
62 }
63
64 public String callMixed(final Integer fixed, final Integer... args) {
65 int result = fixed;
66 if (args != null) {
67 for (final Integer arg : args) {
68 result += arg != null ? arg : -100;
69 }
70 } else {
71 result -= 1000;
72 }
73 return "Mixed:" + result;
74 }
75
76 public String callMixed(final String mixed, final Integer... args) {
77 int result = 0;
78 if (args != null) {
79 for (final Integer arg : args) {
80 result += arg != null ? arg : -100;
81 }
82 } else {
83 result = -1000;
84 }
85 return mixed + ":" + result;
86 }
87
88 public String concat(final String... strs) {
89 if (strs.length <= 0) {
90 return "";
91 }
92 final StringBuilder strb = new StringBuilder(strs[0]);
93 for (int s = 1; s < strs.length; ++s) {
94 strb.append(", ");
95 strb.append(strs[s]);
96 }
97 return strb.toString();
98 }
99 }
100
101 public static class EnhancedContext extends JexlEvalContext {
102 int factor = 6;
103 final Map<String, Object> funcs;
104
105 EnhancedContext(final Map<String, Object> funcs) {
106 this.funcs = funcs;
107 }
108
109 @Override
110 public Object resolveNamespace(final String name) {
111 return funcs.get(name);
112 }
113 }
114
115 public static class ContextualFunctor {
116 private final EnhancedContext context;
117
118 public ContextualFunctor(final EnhancedContext theContext) {
119 context = theContext;
120 }
121
122 public int ratio(final int n) {
123 context.factor -= 1;
124 return n / context.factor;
125 }
126 }
127
128 @Before
129 @Override
130 public void setUp() {
131 asserter = new Asserter(JEXL);
132 }
133
134 @Test
135 public void testCallVarArgMethod() throws Exception {
136 final VarArgs test = new VarArgs();
137 asserter.setVariable("test", test);
138 asserter.assertExpression("test.callInts()", test.callInts());
139 asserter.assertExpression("test.callInts(1)", test.callInts(1));
140 asserter.assertExpression("test.callInts(1,2,3,4,5)", test.callInts(1, 2, 3, 4, 5));
141 asserter.assertExpression("test.concat(['1', '2', '3'])", test.concat(new String[]{"1", "2", "3"}));
142 asserter.assertExpression("test.concat('1', '2', '3')", test.concat("1", "2", "3"));
143
144 }
145
146 @Test
147 public void testCallMixedVarArgMethod() throws Exception {
148 final VarArgs test = new VarArgs();
149 asserter.setVariable("test", test);
150 Assert.assertEquals("Mixed:1", test.callMixed(Integer.valueOf(1)));
151 asserter.assertExpression("test.callMixed(1)", test.callMixed(1));
152
153
154 Assert.assertEquals("Mixed:-999", test.callMixed(Integer.valueOf(1), (Integer[]) null));
155 asserter.assertExpression("test.callMixed(1, null)", "Mixed:-999");
156
157 asserter.assertExpression("test.callMixed(1,2)", test.callMixed(1, 2));
158 asserter.assertExpression("test.callMixed(1,2,3,4,5)", test.callMixed(1, 2, 3, 4, 5));
159 }
160
161 @Test
162 public void testCallJexlVarArgMethod() throws Exception {
163 final VarArgs test = new VarArgs();
164 asserter.setVariable("test", test);
165 Assert.assertEquals("jexl:0", test.callMixed("jexl"));
166 asserter.assertExpression("test.callMixed('jexl')", "jexl:0");
167
168
169 Assert.assertEquals("jexl:-1000", test.callMixed("jexl", (Integer[]) null));
170 asserter.assertExpression("test.callMixed('jexl', null)", "jexl:-1000");
171
172 asserter.assertExpression("test.callMixed('jexl', 2)", test.callMixed("jexl", 2));
173 asserter.assertExpression("test.callMixed('jexl',2,3,4,5)", test.callMixed("jexl", 2, 3, 4, 5));
174 }
175
176 public static class Functor {
177 private boolean overKill = false;
178 private String under = null;
179
180 void setKill(final boolean ok) {
181 overKill = ok;
182 }
183
184 public int ten() {
185 return 10;
186 }
187
188 public int plus10(final int num) {
189 return num + 10;
190 }
191
192 public static int TWENTY() {
193 return 20;
194 }
195
196 public static int PLUS20(final int num) {
197 return num + 20;
198 }
199
200 public static Class<?> NPEIfNull(final Object x) {
201 return x.getClass();
202 }
203
204 public Object over(final String f, final int i) {
205 if (overKill) {
206 throw new UnsupportedOperationException("kill " + f + " + " + i);
207 }
208 return f + " + " + i;
209 }
210
211 public Object over(final String f, final Date g) {
212 return f + " + " + g;
213 }
214
215 public Object over(final String f, final String g) {
216 return f + " + " + g;
217 }
218
219 public void setUnder(final String str) {
220 if (overKill) {
221 throw new UnsupportedOperationException("kill " + str);
222 }
223 under = str;
224 }
225
226 public String getUnder() {
227 if (overKill) {
228 throw new UnsupportedOperationException("kill " + under);
229 }
230 return under;
231 }
232 }
233
234 public static class FunctorOver extends Functor {
235
236 public Object over(final Object f, final Object g) {
237 return f + " + " + g;
238 }
239 }
240
241 @Test
242 public void testInvoke() throws Exception {
243 Functor func = new Functor();
244 Assert.assertEquals(Integer.valueOf(10), JEXL.invokeMethod(func, "ten"));
245 Assert.assertEquals(Integer.valueOf(42), JEXL.invokeMethod(func, "PLUS20", Integer.valueOf(22)));
246 try {
247 JEXL.invokeMethod(func, "nonExistentMethod");
248 Assert.fail("method does not exist!");
249 } catch (final Exception xj0) {
250
251 }
252 try {
253 JEXL.invokeMethod(func, "NPEIfNull", (Object[]) null);
254 Assert.fail("method should have thrown!");
255 } catch (final Exception xj0) {
256
257 }
258
259 Object result;
260 try {
261 result = JEXL.invokeMethod(func, "over", "foo", 42);
262 Assert.assertEquals("foo + 42", result);
263 } catch (final Exception xj0) {
264
265 result = xj0;
266 }
267
268 try {
269 result = JEXL.invokeMethod(func, "over", null, null);
270 Assert.fail("method should have thrown!");
271 } catch (final Exception xj0) {
272
273 result = xj0;
274 }
275
276 func = new FunctorOver();
277 try {
278 result = JEXL.invokeMethod(func, "over", null, null);
279 Assert.assertEquals("null + null", result);
280 } catch (final Exception xj0) {
281 Assert.fail("method should not have thrown!");
282 }
283 }
284
285 @Test
286 public void testAmbiguousInvoke() throws Exception {
287
288 final Functor func = new Functor();
289 final JexlContext ctxt = new MapContext();
290 ctxt.set("func", func);
291 Object result;
292
293 result = JEXL.invokeMethod(func, "over", "foo", 42);
294 Assert.assertEquals("foo + 42", result);
295
296 try {
297 JEXL.invokeMethod(func, "over", "not null", null);
298 Assert.fail("should be ambiguous");
299 } catch (final JexlException.Method xinvoke) {
300 Assert.assertEquals("over(String, Object)", xinvoke.getMethodSignature());
301 }
302
303
304 try {
305 final String[] arg2 = new String[]{"more", "than", "one"};
306 JEXL.invokeMethod(func, "over", "not null", arg2);
307 Assert.fail("should be ambiguous");
308 } catch (final JexlException.Method xinvoke) {
309 Assert.assertEquals("over(String, String[])", xinvoke.getMethodSignature());
310 }
311 }
312
313 @Test
314 public void testTryFailed() throws Exception {
315
316 final Functor func = new Functor();
317 final JexlContext ctxt = new MapContext();
318 ctxt.set("func", func);
319 Object result;
320 final JexlUberspect uber = JEXL.getUberspect();
321
322 final JexlMethod method = uber.getMethod(func, "over", "foo", 42);
323 Assert.assertNotNull(method);
324
325 result = method.tryInvoke("over", func, "foo", 42);
326 Assert.assertEquals("foo + 42", result);
327
328 func.setKill(true);
329 try {
330 method.tryInvoke("over", func, "foo", 42);
331 Assert.fail("should throw TryFailed");
332 } catch (final JexlException.TryFailed xfail) {
333 Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
334 }
335
336 func.setKill(false);
337 final JexlPropertySet setter = uber.getPropertySet(func, "under", "42");
338 result = setter.tryInvoke(func, "under", "42");
339 Assert.assertFalse(setter.tryFailed(result));
340 Assert.assertEquals("42", result);
341
342 final JexlPropertyGet getter = uber.getPropertyGet(func, "under");
343 result = getter.tryInvoke(func, "under");
344 Assert.assertFalse(getter.tryFailed(result));
345 Assert.assertEquals("42", result);
346
347 func.setKill(true);
348 try {
349 setter.tryInvoke(func, "under", "42");
350 Assert.fail("should throw TryFailed");
351 } catch (final JexlException.TryFailed xfail) {
352 Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
353 }
354 func.setKill(false);
355 result = setter.tryInvoke(func, "under", "-42");
356 Assert.assertEquals("-42", result);
357
358 func.setKill(true);
359 try {
360 getter.tryInvoke(func, "under");
361 Assert.fail("should throw TryFailed");
362 } catch (final JexlException.TryFailed xfail) {
363 Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
364 }
365
366 func.setKill(false);
367 result = getter.tryInvoke(func, "under");
368 Assert.assertFalse(getter.tryFailed(result));
369 Assert.assertEquals("-42", result);
370 }
371
372 @Test
373 public void testTryFailedScript() throws Exception {
374
375 final Functor func = new Functor();
376 final JexlContext ctxt = new MapContext();
377 ctxt.set("func", func);
378 Object result;
379 final JexlUberspect uber = JEXL.getUberspect();
380 final JexlScript method = JEXL.createScript("(x, y)->{ func.over(x, y) }");
381
382
383 Assert.assertNotNull(method);
384
385 result = method.execute(ctxt, "foo", 42);
386 Assert.assertEquals("foo + 42", result);
387
388 func.setKill(true);
389 try {
390 method.execute(ctxt, "foo", 42);
391 Assert.fail("should throw TryFailed");
392 } catch (final JexlException xfail) {
393 Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
394 }
395
396 func.setKill(false);
397 final JexlScript setter = JEXL.createScript("(x)->{ func.under = x }");
398
399 result = setter.execute(ctxt, "42");
400 Assert.assertEquals("42", result);
401
402 final JexlScript getter = JEXL.createScript("func.under");
403 Assert.assertEquals("42", result);
404
405 func.setKill(true);
406 try {
407 setter.execute(ctxt, "42");
408 Assert.fail("should throw TryFailed");
409 } catch (final JexlException xfail) {
410 Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
411 }
412 func.setKill(false);
413 result = setter.execute(ctxt, "-42");
414 Assert.assertEquals("-42", result);
415
416 func.setKill(true);
417 try {
418 getter.execute(ctxt);
419 Assert.fail("should throw TryFailed");
420 } catch (final JexlException xfail) {
421 Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
422 }
423
424 func.setKill(false);
425 result = getter.execute(ctxt);
426 Assert.assertEquals("-42", result);
427 }
428
429
430
431
432 @Test
433 public void testMethod() throws Exception {
434
435 asserter.setVariable("foo", new Foo());
436 asserter.assertExpression("foo.bar()", METHOD_STRING);
437 }
438
439 @Test
440 public void testMulti() throws Exception {
441 asserter.setVariable("foo", new Foo());
442 asserter.assertExpression("foo.innerFoo.bar()", METHOD_STRING);
443 }
444
445
446
447
448 @Test
449 public void testStringMethods() throws Exception {
450 asserter.setVariable("foo", "abcdef");
451 asserter.assertExpression("foo.substring(3)", "def");
452 asserter.assertExpression("foo.substring(0,(size(foo)-3))", "abc");
453 asserter.assertExpression("foo.substring(0,size(foo)-3)", "abc");
454 asserter.assertExpression("foo.substring(0,foo.length()-3)", "abc");
455 asserter.assertExpression("foo.substring(0, 1+1)", "ab");
456 }
457
458
459
460
461 @Test
462 public void testStaticMethodInvocation() throws Exception {
463 asserter.setVariable("aBool", Boolean.FALSE);
464 asserter.assertExpression("aBool.valueOf('true')", Boolean.TRUE);
465 }
466
467 @Test
468 public void testStaticMethodInvocationOnClasses() throws Exception {
469 asserter.setVariable("Boolean", Boolean.class);
470 asserter.assertExpression("Boolean.valueOf('true')", Boolean.TRUE);
471 }
472
473 public static class MyMath {
474 public double cos(final double x) {
475 return Math.cos(x);
476 }
477 }
478
479 @Test
480 public void testTopLevelCall() throws Exception {
481 final java.util.Map<String, Object> funcs = new java.util.HashMap<>();
482 funcs.put(null, new Functor());
483 funcs.put("math", new MyMath());
484 funcs.put("cx", ContextualFunctor.class);
485
486 final EnhancedContext jc = new EnhancedContext(funcs);
487
488 JexlExpression e = JEXL.createExpression("ten()");
489 Object o = e.evaluate(jc);
490 Assert.assertEquals("Result is not 10", new Integer(10), o);
491
492 e = JEXL.createExpression("plus10(10)");
493 o = e.evaluate(jc);
494 Assert.assertEquals("Result is not 20", new Integer(20), o);
495
496 e = JEXL.createExpression("plus10(ten())");
497 o = e.evaluate(jc);
498 Assert.assertEquals("Result is not 20", new Integer(20), o);
499
500 jc.set("pi", new Double(Math.PI));
501 e = JEXL.createExpression("math:cos(pi)");
502 o = e.evaluate(jc);
503 Assert.assertEquals(Double.valueOf(-1), o);
504
505 e = JEXL.createExpression("cx:ratio(10) + cx:ratio(20)");
506 o = e.evaluate(jc);
507 Assert.assertEquals(Integer.valueOf(7), o);
508 }
509
510 @Test
511 public void testNamespaceCall() throws Exception {
512 final java.util.Map<String, Object> funcs = new java.util.HashMap<>();
513 funcs.put("func", new Functor());
514 funcs.put("FUNC", Functor.class);
515
516 JexlExpression e = JEXL.createExpression("func:ten()");
517 final JexlEvalContext jc = new EnhancedContext(funcs);
518
519 Object o = e.evaluate(jc);
520 Assert.assertEquals("Result is not 10", new Integer(10), o);
521
522 e = JEXL.createExpression("func:plus10(10)");
523 o = e.evaluate(jc);
524 Assert.assertEquals("Result is not 20", new Integer(20), o);
525
526 e = JEXL.createExpression("func:plus10(func:ten())");
527 o = e.evaluate(jc);
528 Assert.assertEquals("Result is not 20", new Integer(20), o);
529
530 e = JEXL.createExpression("FUNC:PLUS20(10)");
531 o = e.evaluate(jc);
532 Assert.assertEquals("Result is not 30", new Integer(30), o);
533
534 e = JEXL.createExpression("FUNC:PLUS20(FUNC:TWENTY())");
535 o = e.evaluate(jc);
536 Assert.assertEquals("Result is not 40", new Integer(40), o);
537 }
538
539 public static class Edge {
540 private Edge() {
541 }
542
543 public int exec(final int arg) {
544 return 1;
545 }
546
547 public int exec(final int[] arg) {
548 return 20;
549 }
550
551 public int exec(final String arg) {
552 return 2;
553 }
554
555 public int exec(final String... arg) {
556 return 200;
557 }
558
559 public int exec(final Object args) {
560 return 3;
561 }
562
563 public int exec(final Object... args) {
564 return 4;
565 }
566
567 public int exec(final Boolean x, final int arg) {
568 return 1;
569 }
570
571 public int exec(final Boolean x, final int[] arg) {
572 return 20;
573 }
574
575 public int exec(final Boolean x, final String arg) {
576 return 2;
577 }
578
579 public int exec(final Boolean x, final Object args) {
580 return 3;
581 }
582
583 public int exec(final Boolean x, final Object... args) {
584 return 4;
585 }
586
587 public Class<?>[] execute(final Object... args) {
588 final Class<?>[] clazz = new Class<?>[args.length];
589 for (int a = 0; a < args.length; ++a) {
590 clazz[a] = args[a] != null ? args[a].getClass() : Void.class;
591 }
592 return clazz;
593 }
594 }
595
596 private boolean eqExecute(final Object lhs, final Object rhs) {
597 if (lhs instanceof Class<?>[] && rhs instanceof Class<?>[]) {
598 final Class<?>[] lhsa = (Class<?>[]) lhs;
599 final Class<?>[] rhsa = (Class<?>[]) rhs;
600 return Arrays.deepEquals(lhsa, rhsa);
601 }
602 return false;
603 }
604
605 @Test
606 public void testNamespaceCallEdge() throws Exception {
607 final java.util.Map<String, Object> funcs = new java.util.HashMap<>();
608 final Edge func = new Edge();
609 funcs.put("func", func);
610
611 Object o;
612 Object c;
613 JexlExpression e;
614 final JexlEvalContext jc = new EnhancedContext(funcs);
615 try {
616 for (int i = 0; i < 2; ++i) {
617 e = JEXL.createExpression("func:exec([1, 2])");
618 o = e.evaluate(jc);
619 Assert.assertEquals("exec(int[] arg): " + i, 20, o);
620
621 e = JEXL.createExpression("func:exec(1, 2)");
622 o = e.evaluate(jc);
623 Assert.assertEquals("exec(Object... args): " + i, 4, o);
624
625 e = JEXL.createExpression("func:exec([10.0, 20.0])");
626 o = e.evaluate(jc);
627 Assert.assertEquals("exec(Object args): " + i, 3, o);
628
629 e = JEXL.createExpression("func:exec('1', 2)");
630 o = e.evaluate(jc);
631 Assert.assertEquals("exec(Object... args): " + i, 4, o);
632
633
634 Assert.assertEquals("exec(String... args): " + i, func.exec("1", "2"), func.exec(new String[]{"1", "2"}));
635 e = JEXL.createExpression("func:exec(['1', '2'])");
636 o = e.evaluate(jc);
637 Assert.assertEquals("exec(String... args): " + i, func.exec(new String[]{"1", "2"}), o);
638 e = JEXL.createExpression("func:exec('1', '2')");
639 o = e.evaluate(jc);
640 Assert.assertEquals("exec(String... args): " + i, func.exec("1", "2"), o);
641
642 e = JEXL.createExpression("func:exec(true, [1, 2])");
643 o = e.evaluate(jc);
644 Assert.assertEquals("exec(int[] arg): " + i, 20, o);
645
646 e = JEXL.createExpression("func:exec(true, 1, 2)");
647 o = e.evaluate(jc);
648 Assert.assertEquals("exec(Object... args): " + i, 4, o);
649
650 e = JEXL.createExpression("func:exec(true, ['1', '2'])");
651 o = e.evaluate(jc);
652 Assert.assertEquals("exec(Object args): " + i, 3, o);
653
654 e = JEXL.createExpression("func:exec(true, '1', '2')");
655 o = e.evaluate(jc);
656 Assert.assertEquals("exec(Object... args): " + i, 4, o);
657
658 e = JEXL.createExpression("func:execute(true, '1', '2')");
659 o = e.evaluate(jc);
660 c = func.execute(Boolean.TRUE, "1", "2");
661 Assert.assertTrue("execute(Object... args): " + i, eqExecute(o, c));
662
663 e = JEXL.createExpression("func:execute([true])");
664 o = e.evaluate(jc);
665 c = func.execute(new boolean[]{true});
666 Assert.assertTrue("execute(Object... args): " + i, eqExecute(o, c));
667 }
668 } catch (final JexlException xjexl) {
669 Assert.fail(xjexl.toString());
670 }
671 }
672
673 public static class ScriptContext extends MapContext implements JexlContext.NamespaceResolver {
674 Map<String, Object> nsScript;
675
676 ScriptContext(final Map<String, Object> ns) {
677 nsScript = ns;
678 }
679
680 @Override
681 public Object resolveNamespace(final String name) {
682 if (name == null) {
683 return this;
684 }
685 if ("script".equals(name)) {
686 return nsScript;
687 }
688 if ("functor".equals(name)) {
689 return (NamespaceFunctor) context -> {
690 final Map<String, Object> values = new HashMap<>();
691 if ("gin".equals(context.get("base"))) {
692 values.put("drink", "gin fizz");
693 } else {
694 values.put("drink", "champaign");
695 }
696 return values;
697 };
698 }
699 return null;
700 }
701 }
702
703 @Test
704 public void testScriptCall() throws Exception {
705 JexlContext context = new MapContext();
706 final JexlScript plus = JEXL.createScript("a + b", new String[]{"a", "b"});
707 context.set("plus", plus);
708 JexlScript forty2 = JEXL.createScript("plus(4, 2) * plus(4, 3)");
709 Object o = forty2.execute(context);
710 Assert.assertEquals("Result is not 42", new Integer(42), o);
711
712 final Map<String, Object> foo = new HashMap<>();
713 foo.put("plus", plus);
714 context.set("foo", foo);
715 forty2 = JEXL.createScript("foo.plus(4, 2) * foo.plus(4, 3)");
716 o = forty2.execute(context);
717 Assert.assertEquals("Result is not 42", new Integer(42), o);
718
719 context = new ScriptContext(foo);
720 forty2 = JEXL.createScript("script:plus(4, 2) * script:plus(4, 3)");
721 o = forty2.execute(context);
722 Assert.assertEquals("Result is not 42", new Integer(42), o);
723
724 final JexlArithmetic ja = JEXL.getArithmetic();
725 final JexlMethod mplus = new JexlMethod() {
726 @Override
727 public Object invoke(final Object obj, final Object ... params) throws Exception {
728 if (obj instanceof Map<?, ?>) {
729 return ja.add(params[0], params[1]);
730 }
731 throw new Exception("not a script context");
732 }
733
734 @Override
735 public Object tryInvoke(final String name, final Object obj, final Object ... params) {
736 try {
737 if ("plus".equals(name)) {
738 return invoke(obj, params);
739 }
740 } catch (final Exception xany) {
741
742 }
743 return this;
744 }
745
746 @Override
747 public boolean tryFailed(final Object rval) {
748
749 return rval == this;
750 }
751
752 @Override
753 public boolean isCacheable() {
754 return true;
755 }
756
757 @Override
758 public Class<?> getReturnType() {
759 return Object.class;
760 }
761 };
762
763 foo.put("PLUS", mplus);
764 forty2 = JEXL.createScript("script:PLUS(4, 2) * script:PLUS(4, 3)");
765 o = forty2.execute(context);
766 Assert.assertEquals("Result is not 42", new Integer(42), o);
767
768 context.set("foo.bar", foo);
769 forty2 = JEXL.createScript("foo.'bar'.PLUS(4, 2) * foo.bar.PLUS(4, 3)");
770 o = forty2.execute(context);
771 Assert.assertEquals("Result is not 42", new Integer(42), o);
772 }
773
774 @Test
775 public void testFizzCall() throws Exception {
776 final ScriptContext context = new ScriptContext(new HashMap<String, Object>());
777
778 JexlScript bar = JEXL.createScript("functor:get('drink')");
779 Object o;
780 o = bar.execute(context);
781 Assert.assertEquals("Wrong choice", "champaign", o);
782 context.set("base", "gin");
783 o = bar.execute(context);
784 Assert.assertEquals("Wrong choice", "gin fizz", o);
785
786
787 context.set("base", "wine");
788 bar = JEXL.createScript("var glass = functor:get('drink'); base = 'gin'; functor:get('drink')");
789 o = bar.execute(context);
790 Assert.assertEquals("Wrong choice", "champaign", o);
791 }
792
793 public static class ZArithmetic extends JexlArithmetic {
794 public ZArithmetic(final boolean astrict) {
795 super(astrict);
796 }
797
798 public int zzzz(final int z) {
799 return 38 + z;
800 }
801 }
802
803 public static class ZSpace {
804 public int zzz(final int z) {
805 return 39 + z;
806 }
807 }
808
809 public static class ZContext extends MapContext {
810 public ZContext(final Map<String,Object> map) {
811 super(map);
812 }
813
814 public int zz(final int z) {
815 return 40 + z;
816 }
817
818 public int z(final int z) {
819 return 181 + z;
820 }
821 }
822
823 @Test
824 public void testVariousFunctionLocation() throws Exception {
825
826 final Map<String, Object> vars = new HashMap<>();
827 final Map<String,Object> funcs = new HashMap<>();
828 funcs.put(null, new ZSpace());
829 final JexlEngine jexl = new JexlBuilder().namespaces(funcs).arithmetic(new ZArithmetic(true)).create();
830
831 final JexlContext zjc = new ZContext(vars);
832 final String z41 = "z(41)";
833 final JexlScript callz41 = jexl.createScript(z41);
834 Object onovar = callz41.execute(zjc);
835 Assert.assertEquals(222, onovar);
836
837
838 final JexlScript z241 = jexl.createScript("(x)->{ return x + 241}");
839 vars.put("z", z241);
840 final Object oglobal = callz41.execute(zjc);
841 Assert.assertEquals(282, oglobal);
842
843 vars.remove("z");
844 onovar = callz41.execute(zjc);
845 Assert.assertEquals(222, onovar);
846
847
848 final String slocal = "var z = (x)->{ return x + 141}; z(1)";
849 final JexlScript jlocal = jexl.createScript(slocal);
850 final Object olocal = jlocal.execute(zjc);
851 Assert.assertEquals(142, olocal);
852
853
854 Assert.assertEquals(42, jexl.createScript("zz(2)").execute(zjc));
855 Assert.assertEquals(42, jexl.createScript("zzz(3)").execute(zjc));
856 Assert.assertEquals(42, jexl.createScript("zzzz(4)").execute(zjc));
857 }
858
859
860 }